链接:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=688&pid=1003
题意:中文题,给你f1,f2,fn=a^b+fn-1^c+fn-2,让你求fn
分析:看公式一眼矩阵快速幂,但是式子里面有fn-1^c,直接上矩阵是求不出的,我们可以观察到式子的每项都是以a为底的数,f1=a^0,f2=a^b,f3=a^(b+bc),f4=a^(b+(b+bc)*c+b);
设gx为fx的指数表达式,则gn=b+gn-1*c+gn-2,我们现在可以对g进行矩阵快速幂求出第n项的指数,然后快速幂求出最后的答案。
注意,指数取模要根据费马小定理:a^n%p与a^(n%(p-1))%p同余,所以指数的模减一。
还有数据中有a%p==0,如果不特判结果就错了。
代码:
#include <algorithm> #include <iostream> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <vector> #include <queue> #include <cmath> #include <stack> #include <set> #include <map> #include <ctime> #define INF 0x3f3f3f3f #define Mn 100010 #define Mm 200010 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul (u<<1) #define ur (u<<1)|1 using namespace std; typedef long long ll; struct Matrix { ll mt[3][3]; Matrix() { for(int i=0; i<3; i++) for(int j=0; j<3; j++) mt[i][j]=0; } }; Matrix Mult(Matrix b,Matrix a,ll p) { Matrix c; for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) (c.mt[i][j]+=a.mt[i][k]*b.mt[k][j]%p)%=p; return c; } Matrix pow(Matrix a,ll n,ll p) { Matrix re; for(int i=0; i<3; i++) re.mt[i][i]=1; while(n) { if(n%2) re=Mult(re,a,p); a=Mult(a,a,p); n>>=1; } return re; } ll pow(ll a,ll n,ll p) { int b=1; while(n) { if(n%2) b=a*b%p; a=a*a%p; n>>=1; } return b; } int main() { int t; scanf("%d",&t); while(t--) { int a,b,c; ll n,p; Matrix init,tr; scanf("%I64d%d%d%d%I64d",&n,&a,&b,&c,&p); init.mt[0][0]=b; init.mt[2][0]=b; tr.mt[0][0]=1; tr.mt[1][2]=1; tr.mt[2][0]=1; tr.mt[2][1]=1; tr.mt[2][2]=c; if(n==1) { printf("1\n"); } else if(n==2) { printf("%I64d\n",pow((ll)a,b,p)); } else { if(a%p==0) printf("0\n"); else { init=Mult(init,pow(tr,n-2,p-1),p-1); printf("%I64d\n",pow((ll)a,init.mt[2][0],p)); } } } return 0; }