此题对数学知识的要求比较高,9楼版主所说的循环,程序上的验证是正确的,从数学原理上的解释,我还没有弄明白,望能解惑。
下面是我从另一个角度的探索,从斐波那契的递推公式Fn=Fn-1+Fn-2,其中F1=F2=1可以得出以下两个关系,
F(n+m-1)=F(n-1)*F(m-1)+F(n)*F(m)
F(n+m)=F(n-1)*F(m)+F(n)*(F(m-1)+F(m))
这两个公式可以做到,从n-1项,n项,m-1项,m项这4项的值得到m+n-1项,m+n项的值,大概就是可以做到两项之和,这样在计算某一项时,就可以不用一项一项的去求,从某一项开始,直接加上一个合适的项就可以了。以下是代码实现:
下面是我从另一个角度的探索,从斐波那契的递推公式Fn=Fn-1+Fn-2,其中F1=F2=1可以得出以下两个关系,
F(n+m-1)=F(n-1)*F(m-1)+F(n)*F(m)
F(n+m)=F(n-1)*F(m)+F(n)*(F(m-1)+F(m))
这两个公式可以做到,从n-1项,n项,m-1项,m项这4项的值得到m+n-1项,m+n项的值,大概就是可以做到两项之和,这样在计算某一项时,就可以不用一项一项的去求,从某一项开始,直接加上一个合适的项就可以了。以下是代码实现:
程序代码:
#include<stdio.h> #include<stdlib.h> #define modN 10007 int main() { unsigned int f0,f1 ,rs0,rs1; unsigned int i,n,m,end,temp0,temp1; while(1) { if(scanf("%d",&n)==EOF )break; m=n; f0=0; f1=1; rs0=1; rs1=0; i=1; end=(m&0xffff0000)==0?16:32;//m<=0xffff0000时只计算至二进制数低16位 while(i<=end) { if (m&1) { // F(n+m-1)=F(n-1)*F(m-1)+F(n)*F(m) // F(n+m)=F(n-1)*F(m)+F(n)*(F(m-1)+F(m)) // 从rs0,rs1,f0,f1得到rs1+f1-1,rs1+f1 各项值的累加 temp0=(rs0*f0+rs1*f1)%modN; temp1=(rs0*f1+rs1*(f0+f1))%modN; rs0=temp0; rs1=temp1; } // F(n+m-1)=F(n-1)*F(m-1)+F(n)*F(m) // F(n+m)=F(n-1)*F(m)+F(n)*(F(m-1)+F(m)) // 从f0,f1,f0,f1得到f0+f1-1,f0+f1 项数增加一倍,也就是二进制位向上一位 f1 始终记录2^i项的值 temp0=(f0*f0+f1*f1)%modN; temp1=(f0*f1+f1*(f0+f1))%modN; f0=temp0; f1=temp1; m/=2; i++; } printf("%u\n",rs1); } return 1; }