神奇的嵌套斐波那契数列 NOIP模拟赛

【问题描述】 令𝑓(𝑛)为斐波那契数列第𝑛项,其中𝑓(0) = 0, 𝑓(1) = 1, 𝑓(𝑛) = 𝑓(𝑛 − 1) + 𝑓(𝑛 − 2)。 所以要干啥呢? 求𝑓(𝑓(𝑛))。

【输入格式】 第一行一个整数𝑇代表数据组数。 接下来𝑇行每行一个整数𝑛。

【输出格式】 𝑇行每行一个整数代表答案对10^9 + 7取模的值。

【样例输入】 4 0 1 2 6

【样例输出】 0 1 1 21

【数据规模与约定】 对于20%的数据,1 ≤ 𝑛 ≤ 15。 对于40%的数据,1 ≤ 𝑛 ≤ 90。 对于70%的数据,1 ≤ 𝑛 ≤ 10^5。 对于100%的数据,1 ≤ 𝑇 ≤ 10^3 , 1 ≤ 𝑛 ≤ 10^100。

 

我做这道题的时候,看到 n<=10^100 是完全懵逼的。我还不能手敲高精度啊,能不能友好一点?(事实上本题可以避开高精度)

从 mod10^9+7 可以猜测本题函数是否具有周期性,暴力枚举实验证明确有周期性,事实上周期是 329616,但不同的暴力程序推出来不一样(为什么?),有的是2e9+16,有的是更大的数字

有了周期,一切都好办了。

会矩阵快速幂求斐波那契数列吗?那就好了。n模了周期之后,就算剩下的n还大到2e10,也能在O(logn)的时间复杂度内求解。

至于极大的n,可以逐字节读入取模,避开高精度。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 using namespace std;
  5 const long long mod1=1000000007,mod2=2000000016,mod3=329616;
  6 struct matrix{
  7     long long shu[3][3];
  8     int n,m;
  9     matrix operator + (matrix a1){
 10         matrix new1;
 11         new1.n=n;
 12         new1.m=a1.m;
 13         memset(new1.shu,0,sizeof(new1.shu));
 14         for(int i=1;i<=n;i++){
 15             for(int k=1;k<=a1.m;k++)
 16             {
 17                 for(int z=1;z<=m;z++)
 18                 new1.shu[i][k]=(new1.shu[i][k]+shu[i][z]*a1.shu[z][k])%mod2;
 19             }
 20         }
 21         return new1;
 22     }
 23     matrix operator * (matrix a1){
 24         matrix new1;
 25         new1.n=n;
 26         new1.m=a1.m;
 27         memset(new1.shu,0,sizeof(new1.shu));
 28         for(int i=1;i<=n;i++){
 29             for(int k=1;k<=a1.m;k++)
 30             {
 31                 for(int z=1;z<=m;z++)
 32                 new1.shu[i][k]=(new1.shu[i][k]+shu[i][z]*a1.shu[z][k])%mod1;
 33             }
 34         }
 35         return new1;
 36     }
 37     
 38 };
 39 matrix a,b,c;
 40 char s[107];
 41 matrix kuai(matrix c,long long a){
 42     matrix ans,e=c;
 43     int first=1;
 44     while(a){
 45         if(a&1){
 46             if(first){
 47                 first=0;
 48                 ans=e;
 49             }
 50             else ans=ans+e;
 51         }
 52         e=e+e;
 53         a>>=1;
 54     }
 55     return ans;
 56 }
 57 matrix kuai1(matrix c,long long a){
 58     matrix ans,e=c;
 59     int first=1;
 60     while(a){
 61         if(a&1){
 62             if(first){
 63                 first=0;
 64                 ans=e;
 65             }
 66             else ans=ans*e;
 67         }
 68         e=e*e;
 69         a>>=1;
 70     }
 71     return ans;
 72 }
 73 int main(){
 74     int t;
 75     scanf("%d",&t);
 76     while(t--){
 77         scanf("%s",s);
 78         long long tmp=0;
 79         int l1=strlen(s);
 80         for(int i=0;i<l1;i++)
 81         tmp=(tmp*10+(s[i]-'0'))%mod3;
 82         a.n=1;a.m=2;a.shu[1][1]=a.shu[1][2]=1;
 83         c.n=c.m=2;
 84         c.shu[1][1]=0;
 85         c.shu[1][2]=c.shu[2][1]=c.shu[2][2]=1;
 86         long long e=0;
 87         if(tmp==0){
 88             e=0;
 89         }
 90         else if(tmp==1||tmp==2){
 91             e=1;
 92         }
 93         else{
 94             matrix c1=kuai(c,tmp-2);
 95             matrix t1=a+c1;
 96             e=t1.shu[1][2];
 97         }
 98         long long ans=0;
 99         if(e==0){
100             ans=0;
101         }
102         else if(e==1||e==2){
103             ans=1;
104         }
105         else{
106             matrix c1=kuai1(c,e-2);
107             matrix t2=a*c1;
108             ans=t2.shu[1][2];
109         }
110         printf("%lld\n",ans);
111     }
112     return 0;
113 }
View Code

 

posted @ 2017-10-19 22:17  JayWang  阅读(389)  评论(0编辑  收藏  举报