zoukankan      html  css  js  c++  java
  • Sequence (矩阵快速幂+快速幂+费马小定理)

            Holion August will eat every thing he has found. 

            Now there are many foods,but he does not want to eat all of them at once,so he find a sequence. 

    fn=⎧⎩⎨⎪⎪1,ab,abfcn1fn2,n=1n=2otherwisefn={1,n=1ab,n=2abfn−1cfn−2,otherwise 

            He gives you 5 numbers n,a,b,c,p,and he will eat fnfn foods.But there are only p foods,so you should tell him fnfn mod p.

    Input        The first line has a number,T,means testcase. 

            Each testcase has 5 numbers,including n,a,b,c,p in a line. 

        1T10,1n1018,1a,b,c109    1≤T≤10,1≤n≤1018,1≤a,b,c≤109,pp is a prime number,and p109+7p≤109+7.
    Output        Output one number for each case,which is fnfn mod p.Sample Input

    1
    5 3 3 3 233

    Sample Output

    190



    代码:
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<set>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    
    const int maxn=1e5+5;
    typedef long long ll;
    using namespace std;
    
    struct mat
    {
        ll s[3][3];
    };
    ll nn,a,b,c,p;
    ll ksm(ll x,ll y)
    {
        ll ans=1;
        while(y)
        {
            if(y&1)
            ans=(ans*x)%p;
            y>>=1;
            x=x*x%p;
        }
        return ans;
    }
    mat Mul(mat x,mat y)
    {
        mat ans;
        memset(ans.s,0,sizeof(ans.s));
        for(int t=0;t<3;t++)
        {
            for(int j=0;j<3;j++)
            {
                for(int k=0;k<3;k++)
                {
                    ans.s[t][j]=(ans.s[t][j]+(x.s[t][k]*y.s[k][j]))%(p-1);//费马小定理 
                }
            }
        }
        return ans;
    }
    mat ans;
    ll QuickPow(ll n)
    {
        mat res;
        memset(res.s,0,sizeof(res.s));
        res.s[0][0]=c;
        res.s[0][1]=1;
        res.s[0][2]=1;
        res.s[1][0]=1;
        res.s[2][2]=1;
        while(n)
        {
            if(n&1)
            {
                ans=Mul(res,ans);
            }
            n>>=1;
            res=Mul(res,res);
        }
        return ans.s[0][0];
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%lld%lld%lld%lld%lld",&nn,&a,&b,&c,&p);
            if(nn==1)
            {
                printf("1
    ");
            }
            else if(nn==2)
            {
                printf("%lld
    ",ksm(a,b));
            }
            else
            {
                ans.s[0][0]=b;
                ans.s[1][0]=0;
                ans.s[2][0]=b;
                ll ss=QuickPow(nn-2);
                printf("%lld
    ",ksm(a,ss+p-1));//费马小定理 
            }
        }
        
        return 0;
    }
  • 相关阅读:
    Java中的变量
    Java是什么
    leetcode 75. 颜色分类
    leetcode 283. 移动零
    剑指 Offer 65. 不用加减乘除做加法
    剑指 Offer 53
    剑指 Offer 58
    剑指 Offer 58
    剑指 Offer 57
    剑指 Offer 57. 和为s的两个数字
  • 原文地址:https://www.cnblogs.com/Staceyacm/p/10896830.html
Copyright © 2011-2022 走看看