刷清橙OJ--A1080.Fibonacci

来源:互联网 发布:卫星拍摄软件 编辑:程序博客网 时间:2024/05/17 06:56
问题:
A1080. Fibonacci
时间限制:1.0s   内存限制:512.0MB  
总提交次数:1574   AC次数:473   平均分:42.40
问题描述
  Fibonacci数是组合数学中非常重要的一个数列,它的递推公式是:
  F(1)=F(2)=1
  F(n)=F(n-1)+F(n-2)
  当然,用这个公式来计算F(n)是非常慢的,当计算F(n)时需要从F(1)一直计算到F(n)。Fibonacci数列还满足一些其他的公式,如:
  F(a+b+1)=F(a+1)*F(b+1)+F(a)*F(b)
  利用这个公式,可以加速Fibonacci数的计算。我们考虑同时计算F(2n+1)和F(2n),则按照上面的公式:
  F(2n+1)=F(n+1)*F(n+1)+F(n)*F(n)
  F(2n)=F(n+1)*F(n)+F(n)*F(n-1)=F(n+1)*F(n)+F(n)*(F(n+1)-F(n))
  这样,F(2n+1)和F(2n)的计算变为了F(n+1)和F(n)的计算,即下标变为了原来的一半。重复利用这种方法,可以每次让下标变为原来的一半,总共需要大约log n次计算(以2为底)。
  当n较大时,后面的方法就比直接的递推要快得多,比如当n=1000000时,后面的方法大概需要20次计算,而直接递推的方法大概需要1000000次计算,现在请你用这种方法计算F(n)和F(n+1)。
  由于答案非常大,你只需要计算F(n)和F(n+1)除m的余数即可。
  注意,上述公式在除m的余数下仍是满足的,即令g(n)是F(n)除m的余数,则
  g(2n+1)=(g(n+1)*g(n+1)+g(n)*g(n))%m
  g(2n)=(g(n+1)*g(n)+g(n)*(g(n+1)-g(n)+m))%m
  在g(2n)的公式中多了一个+m,是为了在运算中不出现负数。
  参数保证n为正整数,m不大于10000。


这是一道完善程序的试题,你只需要在下面程序标注的"@你的代码"的位置补充适当的语句或语句段使程序能正确运行即可,在提交的时候,你要提交的内容只包括补充的内容,不包括其他的代码。
  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. // 计算F(n)和F(n+1)除m的余数,分别放入fn和fn1中。
  5. void calcF(int n, int m, int &fn, int &fn1)
  6. {
  7. @你的代码
  8. }

代码:

if(n==1) {fn=fn1=1%m;}     else     if (n%2==0)     {        calcF(n/2,m,fn,fn1);        int f=fn,f1=fn1;        fn=(f1*f+f*(f1-f+m))%m;        fn1=(f1*f1+f*f)%m;     }     else     {        int ans1,ans2;                calcF((n+1)/2,m,fn,fn1);        ans1=(fn1*fn+fn*(fn1-fn+m))%m;        calcF((n-1)/2,m,fn,fn1);        ans2=(fn1*fn1+fn*fn)%m;                fn=ans2;fn1=ans1;     }
个人想法:代码来自试题讨论

原创粉丝点击