前言
这题是昨天晚上快到12点的时候AC的,因此没来得及写题解,今天中午补一下题解。
先放题目链接:P1255 数楼梯
解题思路:
这题其实还是蛮简单的,记
f
[
N
]
f[N]
f[N]为台阶数为N的时候有的走法数量。先来看三个特殊情况,(1)当N=0的时候,没有台阶也就不存在走的方式(这里会被输入数据卡一下),因此
f
[
0
]
=
0
f[0]=0
f[0]=0 (2)当N=1的时候,就一种上楼方法,一步到位,因此
f
[
1
]
=
1
f[1]=1
f[1]=1(3)当N=2的时候,如果先登一步,再登一步,是一种,第二种是一次登两步,所以这时候是2,即
f
[
2
]
=
2
f[2]=2
f[2]=2。接着往下再看,当N>2的时候,我想要登上去,有两种情况,一种是处于N-1阶台阶处走一步,登顶;另一种是处于N-2阶台阶处直接走两步,登顶,那么归纳起来就是
f
[
N
]
=
f
[
N
−
1
]
+
f
[
N
−
2
]
f[N]=f[N-1]+f[N-2]
f[N]=f[N−1]+f[N−2]。这里,N=2情况不符合,那就分开讨论,在计算
f
[
1
]
−
f
[
N
]
f[1]-f[N]
f[1]−f[N]时假设它为1,当输入数据N=0直接输出0。但是在这里我们可以看到,
f
[
N
]
f[N]
f[N]的本质就是斐波那契数列。
递推关系式确定了,剩下的一个问题就是模拟高精度。因为输入数据中N最大为5000,而
f
[
5000
]
f[5000]
f[5000]实际上是个很大的数字(试了下,大概是1000位数)所以必须去模拟这样的精度。我的方法是开一个2000多长度的char数组,然后数组从低位到高位依次从0开始存放,加的时候也是对应位相加,然后考虑进位一直加到最高位。
按照上述做法,还需要考虑空间复杂度的为题,假设每一个number对应一个上述那么大的char数组,而实际上N很小的时候有很多空间会被浪费,实际上如果真的是每一个number对应一个char数组,很容易造成内存空间的爆炸,再来看表达式,发现实际上三个char数组就能解决这个递推关系了,因此可以把空间复杂度很好的控制下来。
最后给出我的AC代码:
#include <stdio.h>
#include <stdlib.h>
struct node{
char a[2000];
};
int main(int argc, char *argv[]){
int N,i,j;
scanf("%d",&N);
if(N>0){
struct node number[3];
for(i=0;i<=2;i++){
if(i==0||i==1){
for(j=0;j<1999;j++){
if(j==0)
number[i].a[j]='1';
else
number[i].a[j]='0';
}
number[i].a[1999]='\0';
}else{
for(j=0;j<1999;j++)
number[i].a[j]='0';
number[i].a[1999]='\0';
}
}
int add=0,order1=0,order2=1,order3=2;
for(i=2;i<=N;i++){
add=0;
for(j=0;j<1999;j++){
if((number[order1].a[j]+number[order2].a[j]-48+add)>=':'){
number[order3].a[j]=number[order1].a[j]+number[order2].a[j]-48+add-10;
add=1;
}else{
number[order3].a[j]=number[order1].a[j]+number[order2].a[j]-48+add;
add=0;
}
}
order1++;
if(order1>2)
order1=0;
order2++;
if(order2>2)
order2=0;
order3++;
if(order3>2)
order3=0;
}
for(i=1998;i>=0;i--){
if(number[order2].a[i]=='0')
;
else
break;
}
while(i>=0){
printf("%c",number[order2].a[i]);
i--;
}
}else{
printf("0");
}
return 0;
}