1. 程式人生 > >HDU 5667 Sequence (矩陣快速冪+費馬小定理)

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

 

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;
}