hdu4921 A Short problem 循环节 矩阵快速幂

传送门

题意:求

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


猜你喜欢

转载自blog.csdn.net/zhubing0331/article/details/80056323