HDU 5667 Sequence (矩阵快速幂+费马小定理)

Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2687    Accepted Submission(s): 896


 

Problem Description

     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,abfcn−1fn−2,n=1n=2otherwise

     He gives you 5 numbers n,a,b,c,p,and he will eat fn foods.But there are only p foods,so you should tell him fn 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.

    1≤T≤10,1≤n≤1018,1≤a,b,c≤109 ,p is a prime number,and p≤109+7 .

 

Output

     Output one number for each case,which is fn mod p.

 

Sample Input

 

1 5 3 3 3 233

 

Sample Output

 

190

 

Source

BestCoder Round #80

 

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6396 6395 6394 6393 6392 

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
ll powmod(ll x,ll y) {ll t;for(t=1;y;y>>=1,x=x*x%p) if(y&1) t=t*x%p;return t;}
const int  maxn =2e5+5;
/*
题目意思很简单,就是要求个递推式。

首先数学直觉,要对两边同时取loga,
令Fn=loga(fn),那么最后我们可以通过快速幂求出Fn,
最后再a^Fn就行了,但是这样有数据范围的限制,
那么再观察,最终结果既然是a的幂次式,直接a%=p,
这样gcd(a,p)=1,根据费马小定理,a^(p-1)%p=1;
那么最终在矩阵快速幂的时候,要对p-1取模,这样思路就清晰了。

有个wrong点,我感觉不加没事,但是真的不加就wrong了,
就是特判a%p是否为0,如果是直接puts(0)。
*/
ll n,a,b,c,p;

struct jz
{
    ll a[3][3];
    jz(){memset(a,0,sizeof(a));}
    jz operator*( jz y)
    {
        jz ans;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            {
                ans.a[i][j]=0;
                for(int k=0;k<3;k++) ans.a[i][j]=ans.a[i][j]+a[i][k]%(p-1)*y.a[k][j]%(p-1);
                ans.a[i][j]%=(p-1);
            }
        return ans;
    }
};

jz unit;
ll fpow(ll c,ll b,ll n)
{
    jz ans,shu;
    memset(shu.a,0,sizeof(shu.a));
    shu.a[1][0]=1,shu.a[2][2]=1;shu.a[0][0]=c,shu.a[0][1]=1,shu.a[0][2]=b;///矩阵初始化
    
    for(ans=unit;n;n>>=1,shu=shu*shu) if(n&1) ans=shu*ans;///矩阵快速幂
    
    ll ret=(ans.a[0][0]%(p-1)*b%(p-1)+ans.a[0][2]%(p-1))%(p-1);
    return  ret;
}

int main()
{
    for(int i=0;i<3;i++) unit.a[i][i]=1;
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&p);
        a%=p;
        if(a==0) puts("0");////一个wrong点,少这句就wrong
        else if(n==1) printf("%lld\n",1);
        else printf("%lld\n",powmod(a,fpow(c,b,n-2)));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/81697571