HDU 3221 Brute-force Algorithm
![](http://acm.hdu.edu.cn/data/images/3221-1.jpg)
题意:问funny被调用了多少次,结果ModP,P不一定为质数。
首先很容易发现递推公式fn=fn-1*fn-2;写出前几项a,b,a*b,a*b^2,a^2*b^3,a^3*b^5;易发现a,b的指数为斐波那契数列。但是当N大一点时,斐波那契数列便变得非常大。那么此时得用欧拉定理降幂。
![](https://images2015.cnblogs.com/blog/962731/201605/962731-20160526221216616-1844398099.png)
特别要主要使用条件,x>phi(c)。
接着用矩阵快速幂求斐波那契数列,再快速幂求答案即可。
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=1e6+10; int euler[maxn]; ll a,b,m,n; int phi() { for(int i=0;i<maxn;i++) euler[i]=i; for(int i=2;i<maxn;i++) { if(euler[i]==i) { for(int j=i;j<maxn;j+=i) { euler[j]=euler[j]/i*(i-1); } } } } struct Matrix { ll a[2][2]; Matrix(){memset(a,0,sizeof(a));} Matrix operator* (const Matrix &p) { Matrix res; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { for(int k=0;k<2;k++) { res.a[i][j]+=a[i][k]*p.a[k][j]; if(res.a[i][j]>euler[m])//特别要注意这个条件 { res.a[i][j]=res.a[i][j]%euler[m]+euler[m]; } } } } return res; } }ans,base; Matrix quick_pow(Matrix base,ll n) { Matrix res; for(int i=0;i<2;i++) { res.a[i][i]=1; } while(n) { if(n&1) res=res*base; base=base*base; n>>=1; } return res; } ll pow(ll a,ll n) { ll ans=1; while(n) { if(n&1) ans=ans*a%m; a=a*a%m; n>>=1; } return ans; } void Matrix_init() { ans.a[0][0]=1; ans.a[0][1]=1; ans.a[1][0]=0; ans.a[1][1]=0; base.a[0][0]=1; base.a[0][1]=1; base.a[1][0]=1; base.a[1][1]=0; } int main() { int t,cas=0; ll ansa,ansb,faca,facb; phi(); scanf("%d",&t); while(t--) { cas++; scanf("%lld%lld%lld%lld",&a,&b,&m,&n); printf("Case #%d: ",cas); if(n==1) printf("%lld\n",a%m); else if(n==2) printf("%lld\n",b%m); else if(n==3) printf("%lld\n",a*b%m); else if(m==1) printf("0\n"); else { Matrix_init(); ans=ans*quick_pow(base,n-3); faca=ans.a[0][1]; facb=ans.a[0][0]; ansa=pow(a,faca)%m; ansb=pow(b,facb)%m; printf("%lld\n",ansa*ansb%m); } } return 0; }
人,最大的敌人是自己。