思路
众所周知,斐波那契数列在模意义下是有周期的,我们设在模 1 0 9 + 7 10^9+7 109+7 的时候的周期是 T 1 T1 T1,在模 T 1 T1 T1 的时候的周期是 T 2 T2 T2,那么式子就变成了: F ( F ( n m o d T 2 ) m o d T 1 ) F(F(n\bmod T2)\bmod T1) F(F(nmodT2)modT1)。
这个式子是可以用矩乘的,不会矩乘求斐波那契的出门左转。
如何求 T 1 , T 2 T1,T2 T1,T2 呢?暴力!直接上线性递推式求周期!
#include <bits/stdc++.h>
#define int long long
int a,b,ans,mod,tmp;
signed main()
{
cin>>mod;
a = 1,b = 1;
do
ans++,tmp = b,b = (a+b)%mod,a = tmp;
while(a!=1||b!=1);
cout<<ans;
return 0;
}
为什么我写暴力,因为我不会其他的!
你还别说跑得还挺快。
得到 T 1 = 2000000016 , T 2 = 329616 T1=2000000016,T2=329616 T1=2000000016,T2=329616。
用矩乘求就行了。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
template<typename T> void read(T &x)
{
x = 0;
T f = 1;char ch = getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
{
f = -1,ch = getchar();
break;
}
ch = getchar();
}
while(ch>='0'&&ch<='9')
x = ((x<<3)+(x<<1)+ch-48)%329616,ch = getchar();//边快读边取模
x*=f;
}
template<typename T> T read()
{
T x;read(x);return x;
}
template<typename T> void write(T x)
{
if(x<0) x = -x,putchar('-');
if(x<=9) return putchar(x+48),void();
write(x/10);
putchar(x%10+48);
}
template<typename T> void writen(T x)
{
write(x);
puts("");
}
struct node{
int c[5][5];
void clear(int x)
{
for(int i = 0;i<5;i++)
for(int j = 0;j<5;j++)
c[i][j] = x;
}
}a;
node mul(node x,node y,int mod)
{
node res;
res.clear(0);
for(int i = 1;i<=2;i++)
for(int j = 1;j<=2;j++)
for(int k = 1;k<=2;k++)
(res.c[i][j]+=x.c[i][k]*y.c[k][j])%=mod;
return res;
}
int qpow(int y,int mod)
{
node res,x;
x.clear(0);
x.c[1][1] = x.c[1][2] = x.c[2][1] = 1;
res.clear(0);
res.c[1][1] = res.c[1][2] = 1;
if(y==0) return 0;
if(y<2) return 1;
y-=2;
while(y)
{
if(y&1) res = mul(res,x,mod);
y>>=1;
x = mul(x,x,mod);
}
return res.c[1][1];
}
int n;
void solve()
{
read(n);
int m = qpow(n,2000000016ll);
writen(qpow(m,1000000007ll));
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int T;
read(T);
while(T--) solve();
return 0;
}