题意:求
思路:这个题让我对循环节有了新的认知QAQ:我们首先考虑g(n)对1e9+7的循环节,这个确实不大好找……可以猜测一下这个循环节应该是在1e7、1e8的范围,可以多分几次范围,然后慢慢找到这个循环节
ll a=0,b=1,c;
for(ll i=2;i<=300000000;i++)
{
c=(3*b+a)%mod1;
a=b%mod1;
b=c%mod1;
if(a==0&&b==1)
printf("%lld\n",i-1);
}
这样就能找到第一个循环节:222222224
然后我们再考虑g(g(n))的循环节,由于g(n)在0-222222223中有个循环,所以本来是对1e9+7取模的,其实相当于变成了对222222224取模
这样就找到了第二个循环节:183120
类似的就可以找到g(g(g(n)))的循环节:240
找到循环节计算就很容易了QAQ
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=2;
typedef long long ll;
const int mod1=1e9+7;
const int mod2=222222224;
const int mod3=183120;
const int mod4=240;
struct matrix
{
ll m[N][N];
};
matrix matrixmul(matrix a,matrix b,int mod)
{
ll i,j,k;
matrix c;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
c.m[i][j]=0;
for(k=0;k<N;k++)
{
c.m[i][j]+=a.m[i][k]*b.m[k][j]%mod;
}
c.m[i][j]=c.m[i][j]%mod;
}
}
return c;
}
matrix quickpow(ll n,int mod)
{
matrix m={3,1,1,0};
matrix c={1,0,0,1};
while(n>=1)
{
if(n&1)
{
c=matrixmul(c,m,mod);
}
n=n>>1;
m=matrixmul(m,m,mod);
}
return c;
}
int main()
{
ll n;
while(scanf("%lld",&n)!=-1)
{
n=n%mod4;
if(n==0)
{
printf("0\n");
continue;
}
matrix res1=quickpow(n-1,mod3);
ll temp1=res1.m[0][0];
if(temp1==0)
{
printf("0\n");
continue;
}
matrix res2=quickpow(temp1-1,mod2);
ll temp2=res2.m[0][0];
if(temp2==0)
{
printf("0\n");
continue;
}
matrix res3=quickpow(temp2-1,mod1);
ll ans=res3.m[0][0];
printf("%lld\n",ans);
}
return 0;
}