题意:
g(0)=0,g(1)=1;
g(n) = 3g(n - 1) + g(n - 2);
求g(g(g(n))) mod 10^9 + 7
思路:
首先我们得认识到,如果一层一层算是必定会超时的。
其次,取模运算是有循环节的。
step1我们找出g(x)%1000000007的循环节 mod1
step2 设g(g(n)) = g(x) x=g(n) 对mod1 取模得到mod2.
剩下的工作就是进行三次的快速幂运算 从内到外进行。 不理解为啥是从内到外的看这里
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
ll md[]={183120,222222224,1000000007};
/*
const ll mod=1e9+7;
const int maxn=500000000;
int main()
{
ll f0=0,f1=1;
for(int i=1;i<=maxn;i++)
{
ll tmp=(3*f1+f0)%mod;
f0=f1;
f1=tmp;
if(f0==0&&f1==1)
{
cout<<i<<endl;
}
}
return 0;
}
*/
struct mat{
ll m[3][3];
};
mat mul(mat x,mat y,ll mod)
{
mat c;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
c.m[i][j]=0;
for(int k=0;k<2;k++)
{
c.m[i][j]=(c.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod)%mod;
}
}
}
return c;
}
ll pow(mat x,ll y,ll mod)
{
mat ans;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
if(i==j)
{
ans.m[i][j]=1;
}
else{
ans.m[i][j]=0;
}
}
}
while(y)
{
if(y&1)
ans=mul(ans,x,mod);
x=mul(x,x,mod);
y>>=1;
}
return ans.m[0][0];
}
int main(){
ll n;
while(~scanf("%lld",&n)){
mat a;
a.m[0][0]=3;
a.m[0][1]=1;
a.m[1][0]=1;
a.m[1][1]=0;
for(int i=0;i<3;i++)
if(n>=2) n = pow(a,n-1,md[i]);
printf("%lld\n",n);
}
return 0;
}