HDU 5667 Sequence (矩陣快速冪+費馬小定理)
SequenceTime 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. Input The first line has a number,T,means testcase. 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; }