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;
}
原文地址:https://www.cnblogs.com/Staceyacm/p/10896830.html