题意:求
思路:这个题让我对循环节有了新的认知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; }