1.p1255数楼梯
解题思路:斐波那契数列+高精度加法
一定要用高精度加法,否则只有50分左右
#include
using namespace std;
int f[5001][5000]={0};//数组开太大内存会爆掉
void jf(int k){//高精度加法,先加再进位
for(int i=0;i<=4999;i++){
f[k][i]=f[k-1][i]+f[k-2][i];
}
for(int i=0;i<=4999;i++){
f[k][i+1]+=f[k][i]/10;
f[k][i]=f[k][i]%10;
}
}
int main(){
f[1][0]=1;
f[2][0]=2;
int n,flag=0;
cin >> n;
for(int i=3;i<=n;i++){
jf(i);
}//f[n]=f[n-1]+f[n-2]
for(int i=4999;i>=0;i--){
if(f[n][i]!=0){
flag=1;
}
if(flag){
cout << f[n][i];
}
}
if(flag==0){
cout << 0;
}
return 0;
}
2.P1002 [NOIP2002 普及组] 过河卒
解题思路:动态规划+注意边界
输出有多少条路的题是典型的动态规划题
#include
#include
using namespace std;
int m[21][21]={0};
long long f[21][21]={0};
struct node{
int x;
int y;
};
int p[2][8]={{-2,-1,1,2,2,1,-1,-2},{1,2,2,1,-1,-2,-2,-1}};
int main(){
node ma,b;
cin >> b.x >> b.y >> ma.x >> ma.y;
m[ma.x][ma.y]=1;
for(int i=0;i<8;i++){
if(ma.x+p[0][i]>=0 && ma.x+p[0][i]<=20 && ma.y+p[1][i]>=0 && ma.y+p[1][i]<=20){
m[ma.x+p[0][i]][ma.y+p[1][i]]=1;
}
}
if(m[0][1]==0){
f[0][1]=1;
}
if(m[1][0]==0){
f[1][0]=1;
}//以上两步为初始化步骤
for(int i=0;i<=b.x;i++){
for(int j=0;j<=b.y;j++){
if(m[i][j]==1 || i==0&&j==1 || i==1&&j==0){
continue;
}//如果这个点不能走或者是已经初始化的点,不能进行更改
if(i-1>=0 && j-1>=0){
f[i][j]=f[i-1][j]+f[i][j-1];//如果向前两个点都在图内则都加上
}else if(i-1>=0 && j-1<0){
f[i][j]=f[i-1][j];
}else if(i-1<0 && j-1>=0){
f[i][j]=f[i][j-1];
}
}
}
cout << f[b.x][b.y];//输出有多少条路
return 0;
}
3.P1044 [NOIP2003 普及组] 栈
解题思路:转换为卡特兰数
对于序列里的每一个数都有可能是最后一个出栈的,设这个数为X,对于小于X的X-1个数出栈顺序有F[X-1]种,对于大于X的N-X-1个数出栈顺序有F[N-X-1]种,则对于X可以组成的出栈序列有F[X-1]*F[N-X-1]种,遍历X从1到N,就构成了卡特兰数
#include
using namespace std;
long long f[19]={0},sum=0;
int main(){
int n;
cin >> n;
f[0]=1;
f[1]=1;
for(int k=2;k<=n;k++){
for(int i=0;i<=k-1;i++){
f[k]+=f[i]*f[k-i-1];
}
}
cout << f[n];
return 0;
}
4.P1028 [NOIP2001 普及组] 数的计算
解题思路:循环模拟递归
#include
using namespace std;
int f[1001];
int main(){
int n,j;
cin >> n;
f[0]=0;
f[1]=1;
for(int i=2;i<=n;i++){//给出从2到n的每一个数的可能
//递推公式为f[n]=1+f[(n/2)-1]+f[(n/2)-2]+...f[1]
//即n前面能加N/2,N/2-1,...,1其它不行
f[i]=1;
j=i/2;
while(j>0){
f[i]+=f[j];
j--;
}
}
cout << f[n];
return 0;
}
5.P1010 [NOIP1998 普及组] 幂次方
解题思路:递归
用于递归的函数每次输入进去的是一个需要转换成二进制表示的数,所以我们先将其转换为二进制,并且用一个x[16]数组存储。
其次我们对二进制的每一位进行输出,首先需要肯定的是只有该二进制位为1的时候才需要输出,其次我们只直接输出1,2,4的二进制表示,其余位需要进一步转换,所以对于i!=0,1,2的位我们先用2将其包住,再进行递归。
需要注意的是,对于输出的i不是最后一个需要输出的位时,我们要在他们后面加一个+
#include
using namespace std;
int sc(int n){
int x[16],min=-1,i=0;
while(n>0){
x[i]=n%2;
n=n/2;
if(min==-1 && x[i]==1){
min=i;
}
i++;
}
i--;
while(i>=0){
if(x[i]!=0){
if(i==0 || i==1 || i==2){
if(i==0){
cout << "2(0)";
}else if(i==1){
cout << "2";
}else if(i==2){
cout << "2(2)";
}
}else{
cout << "2(";
sc(i);
cout << ")";
}
if(i!=min){
cout << "+";
}
}
i--;
}
}
int main(){
int n;
cin >> n;
sc(n);
return 0;
}
未完待续…