递推+高精度加法 P1255 数楼梯
递推+高精度加法 P1255 数楼梯
思路
- 递推计算,类似斐波拉契,但是由于数据比较大,需要高精度处理
- 斐波那契数列的规律是:每一项等于前两项之和。比如:
F(1)=1
F(2)=1
F(3)=F(1)+F(2)=2
F(4)=F(2)+F(3)=3
F(5)=F(3)+F(4)=5
…
从第10项开始,数值会爆炸式增长:
F(10)=55
F(20)=6765
F(30)=832040
F(40)=102334155
F(50)=12586269025
…
到第50项时,数值已经超过100亿!
高精度来处理才合适!
参考代码
#include<bits/stdc++.h>
using namespace std;
int n,a[5005]={1},b[5005]={1},c[5005]={1},len=1;
void f(){ //斐波那契数列的高精度求和int jw=0;for(int i=0;i<len;i++){ //模拟竖式计算,进位c[i]=a[i]+b[i]+jw;jw=c[i]/10;c[i]=c[i]%10;}if(jw!=0){c[len++]=jw;}for(int i=0;i<len;i++){ //斐波那契数列的结构a[i]=b[i]; // a = b;b[i]=c[i]; // b =c; }
}
int main(){cin>>n;for(int i=2;i<=n;i++){ //从第二个开始f();}for(int i=len-1;i>=0;i--){ //从个位输出,需要逆序输出cout<<c[i];}return 0;
}
解释
高精度计算,为什么计算时不需要逆序相加,而是直接正序计算?
- 数组存储方式:低位在前,高位在后
数组 a, b, c 的每个索引 i 对应数字的 10^i 位。例如:
a[0] 存储个位,a[1] 存储十位,依此类推。
初始值 a[0] = 1 表示斐波那契数列的第一项是 1。
这种存储方式与手工计算时对齐个位的逻辑一致,无需逆序。 - 逐位相加的逻辑
在函数 f() 中,循环 for(int i=0; i<len; i++) 从低位(个位)开始逐位相加:
cpp
c[i] = a[i] + b[i] + jw; // jw 是进位
jw = c[i] / 10; // 计算新的进位
c[i] %= 10; // 保留当前位的值
进位 jw 会自然传递到高位,这与手工计算时“从低位到高位处理进位”的逻辑完全一致。 - 动态扩展高位
如果最高位相加后仍有进位(jw != 0),代码会扩展数组长度:
cpp
if(jw != 0) c[len++] = jw;
这一步直接将进位添加到数组末尾(即更高位),符合数字位数增长的方向。 - 为何不需要逆序?
逆序存储(高位在前):若数组索引 0 对应最高位,则需要逆序遍历数组相加,处理进位时还需反向调整,逻辑复杂。
正序存储(低位在前):直接按索引顺序处理,进位自然传递到高位,无需逆序操作,代码更简洁高效。
示例演示
以计算 F(3) = 2 为例:
初始 a = [1], b = [1](对应数字 1 和 1)。
第一次调用 f():
c[0] = 1 + 1 + 0 = 2,无进位。
结果 c = [2],输出 2。
后续迭代会逐步处理更高位,但始终从低位开始。