http://acm.hdu.edu.cn/showproblem.php?pid=5667
给你 fn=⎧⎩⎨⎪⎪1,ab,abfcn−1fn−2,n=1n=2otherwise ,叫你求 fn 。
首先因为两边都是a为底的,所以取个log,那么a的幂 wn=b+c×wn−1+wn−2 ,这个式子可以用矩阵快速幂算出来。
然后 fn=awn ,这个也用快速幂去算就行了。
要注意的是 Ab%C=Ab%ϕ(c)+ϕ(c)%C
因为 c=p 是素数,所以 ϕ(p)=p−1 ,所以在矩阵乘法里模 p−1 ,算 awn 时模 p 。
然后要注意就是有一个坑,就是当 a%p=0 且 wn%p=0 时, awn%p 理应为0,但 a0 算出来会是1,所以要特判下。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
ll MOD;
const int N=3;
struct matrix
{
ll mat[N][N];
matrix(void)
{
memset(mat,0,sizeof mat);
}
matrix friend operator * (matrix a, matrix b)
{
int n=N;
matrix ans;
for(int i=0 ; i<n ; ++i)
{
for(int j=0 ; j<n ; ++j)
{
int sum=0;
for(int k=0 ; k<n ; ++k)
{
sum+=a.mat[i][k]*b.mat[k][j]%(MOD-1);
sum%=(MOD-1);
}
ans.mat[i][j]=sum;
}
}
return ans;
}
};
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll n,a,b,c;
scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&MOD);
if(n==1)
{
printf("1\n");
continue;
}
if(n==2)
{
printf("%lld\n",b);
continue;
}
if(a%MOD==0)
{
printf("0\n");
continue;
}
matrix A;
A.mat[0][0]=c;A.mat[0][1]=1;A.mat[0][2]=1;
A.mat[1][0]=1;A.mat[1][1]=0;A.mat[1][2]=0;
A.mat[2][0]=0;A.mat[2][1]=0;A.mat[2][2]=1;
matrix ans;
ans.mat[0][0]=1;ans.mat[0][1]=0;ans.mat[0][2]=0;
ans.mat[1][0]=0;ans.mat[1][1]=1;ans.mat[1][2]=0;
ans.mat[2][0]=0;ans.mat[2][1]=0;ans.mat[2][2]=1;
n--;
while(n)
{
if(n&1)
{
ans=ans*A;
}
A=A*A;
n>>=1;
}
ll wn=(ans.mat[1][0]*b+ans.mat[1][2]*b)%(MOD-1);
ll res=1;
while(wn)
{
if(wn&1)
{
res*=a;
res%=MOD;
}
a=a*a;
a%=MOD;
wn>>=1;
}
printf("%lld\n",res);
}
return 0;
}