神奇的嵌套斐波那契数列 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 }