链接:点击打开链接
题意:求出F(a^b)^(F(a^b)^(n-1))%c(F为斐波那契数的值)
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
unsigned long long f[20005]; //注意要使用无符号形
unsigned long long phi(unsigned long long n){ //欧拉函数值
unsigned long long sum=n,i;
for(i=2;i*i<=n;i++){
if(n%i==0){
sum-=sum/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
sum-=sum/n;
return sum;
}
unsigned long long quickmod(unsigned long long a,unsigned long long b,unsigned long long m){
unsigned long long sum=1; //快速幂
a=a%m;
while(b){
if(b&1)
sum=sum*a%m;
b>>=1;
a=a*a%m;
}
return sum;
}
unsigned long long loop(unsigned long long m){
unsigned long long i; //求斐波那契数的循环节
f[0]=0;f[1]=1;f[2]=1;
for(i=3;;i++){
f[i]=(f[i-1]+f[i-2])%m;
if(f[i]==f[1]&&f[i-1]==f[0])
return i-1;
}
}
int main(){ //这道题主要运用了两个性质:
unsigned long long a,b,n,c,i,j,l,ph,cur,sum;//1.a^b≡(amodc)^bmodϕ(c)+ϕ(c)(modc),b>=ϕ(c) ϕ(c)为c的欧拉函数值
int k,t; //2.斐波那契数列有一个性质,它的n次方取模会出现一个循环节.假设循环节长度为len,则F(a^b)modc=F(a^bmodlen)modc
cin>>t;
for(k=1;k<=t;k++){
cin>>a>>b>>n>>c;
printf("Case %d: ",k);
if(c==1){ //c等于0时,模一定为0
printf("0\n");
continue;
} //根据以上性质本题变为求F(a^b)^(F(a^b)^(n-1))%c(F()为斐波那契)
ph=phi(c); //先求出欧拉函数值
l=loop(c); //求循环
cur=quickmod(a,b,l);
cur=f[cur]; //求出F[a^b%len]
if(ph==1){ //欧拉函数为1时单独考虑
cout<<quickmod(cur,n-1,c)<<endl;
continue;
}
l=loop(ph);
sum=quickmod(a,b,l);
sum=f[sum]; //求出关于欧拉函数值F[a^b%len]
sum=quickmod(sum,n-1,ph)+ph;
cur=quickmod(cur,sum,c); //从而求出结果
cout<<cur<<endl;
}
return 0;
}