题目链接
思路:答案是一个递推式ans【n】=ans【n-1】*ans【n-2】,ans【1】=a,ans【2】=b,当n大于3的时候a和b的指数就是斐波那契数列,我们可以用矩阵快速幂算出来,但是还不行,这里的指数可能会很大,还需要用欧拉降幂
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll fib[200];
struct mt{
ll a[3][3];
};
mt t(mt a,mt b,ll mod){
mt res;
int i,j,k;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
res.a[i][j]=0;
for(k=0;k<3;k++){
res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
res.a[i][j]%=mod;
}
}
}
return res;
}
mt power(mt a,ll b,ll mod){
mt res;
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
res.a[i][j]=0;
}
}
res.a[0][0]=res.a[1][1]=res.a[2][2]=1;
while(b){
if(b&1)res=t(res,a,mod);
b>>=1;
a=t(a,a,mod);
}
return res;
}
ll feb(ll n,ll mod){
mt temp;
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
temp.a[i][j]=0;
}
}
temp.a[0][1]=temp.a[1][1]=temp.a[1][0]=1;
mt res=power(temp,n-1,mod);
return (res.a[0][0]+res.a[0][1])%mod;
}
ll quick(ll a,ll b,ll mod){
ll ans=1;
a=a%mod;
while(b!=0){
if(b&1) ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans%mod;
}
ll get_euler(ll n){
ll res=n,a=n;
for (ll i = 2; i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a=a/i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
int main(){
int T;
fib[0] = 1;fib[1] = 1;
for(int i=2;i<=160;i++) fib[i]=fib[i-1]+fib[i-2];
scanf("%d",&T);
for(int j=1;j<=T;++j)
{
ll a,b,n,p;
scanf("%lld%lld%lld%lld",&a,&b,&p,&n);
if(n==1) printf("Case #%d: %lld\n", j, a%p);
else if(n==2) printf("Case #%d: %lld\n", j, b%p);
else if(n==3) printf("Case #%d: %lld\n", j, a*b%p);
else if(a==0||b==0||p==1) printf("Case #%d: %lld\n", j, 0);
else {
if(n<=35){
printf("Case #%d: %lld\n", j, quick(a,fib[n-3],p)*quick(b,fib[n-2],p)%p);continue;//注意一下欧拉降幂的使用条件是指数大于等于欧拉的时候
}
ll x=get_euler(p);
ll t1=feb(n-2,x),t2=feb(n-1,x);
ll ans=quick(a,t1+x,p)%p;
ans*=quick(b,t2+x,p)%p;
printf("Case #%d: %lld\n", j, ans%p);
}
}
}