##题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2814
##题意
给出a,b,n,c,求
F
(
a
b
)
F
(
a
b
)
n
−
1
%
c
F(a^{b})^{F(a^b)^{n-1}}\%c
F(ab)F(ab)n−1%c,F(x)表示斐波那契函数。
##思路
先利用
a
b
%
p
=
a
φ
(
p
)
+
b
%
φ
(
p
)
a^{b}\%p = a^{\varphi (p) + b\%\varphi (p)}
ab%p=aφ(p)+b%φ(p)降幂,再用找斐波那契模一个数有循环节的特点降
a
b
a^{b}
ab,这两个比较大的数降完以后就是无脑快速幂。
下面是推倒过程:
F
(
a
b
)
F
(
a
b
)
n
−
1
%
c
F(a^{b})^{F(a^b)^{n-1}}\%c
F(ab)F(ab)n−1%c
=
(
F
(
a
b
)
%
c
)
F
(
a
b
)
n
−
1
%
c
=(F(a^{b})\%c)^{F(a^b)^{n-1}}\%c
=(F(ab)%c)F(ab)n−1%c
我们先处理底
F
(
a
b
)
%
c
F(a^{b})\%c
F(ab)%c,
∵
F
(
x
)
%
c
存
在
循
环
节
,
设
m
o
d
为
循
环
的
周
期
,
p
o
s
为
循
环
的
起
始
位
置
\because F(x)\%c存在循环节,设mod为循环的周期,pos为循环的起始位置
∵F(x)%c存在循环节,设mod为循环的周期,pos为循环的起始位置
∴
F
(
a
b
)
%
c
=
F
(
(
a
b
−
p
o
s
)
%
m
o
d
+
p
o
s
)
%
c
=
F
(
a
b
%
m
o
d
+
p
o
s
−
p
o
s
%
m
o
d
)
%
c
\therefore F(a^b)\%c=F((a^b-pos)\%mod+pos)\%c=F(a^b\%mod+pos-pos\%mod)\%c
∴F(ab)%c=F((ab−pos)%mod+pos)%c=F(ab%mod+pos−pos%mod)%c
然后是幂,用上面的公式
原
式
=
(
F
(
a
b
)
%
c
)
ϕ
(
c
)
+
F
(
a
b
)
n
−
1
%
ϕ
(
c
)
%
c
原式=(F(a^{b})\%c)^{\phi(c)+F(a^b)^{n-1}\%\phi(c)}\%c
原式=(F(ab)%c)ϕ(c)+F(ab)n−1%ϕ(c)%c
F
(
a
b
)
n
−
1
%
ϕ
(
c
)
=
(
F
(
a
b
)
%
ϕ
(
c
)
)
n
−
1
%
ϕ
(
c
)
F(a^b)^{n-1}\%\phi(c)=(F(a^b)\%\phi(c))^{n-1}\%\phi(c)
F(ab)n−1%ϕ(c)=(F(ab)%ϕ(c))n−1%ϕ(c)
和上面的处理方法一样
##代码
#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#define ULL unsigned long long
#define mp(x,y) make_pair(x,y)
using namespace std;
int phi[310];
int fib1[90010],fib2[90010];
map<pair<int,int>,int> fibb;
int pos[90010];
void init(){
for(int i=1;i<=300;++i) phi[i]=i;
for(int i=2;i<=300;i+=2) phi[i]/=2;
for(int i=3;i<=300;i+=2)
if(phi[i]==i)
for(int j=i;j<=300;j+=i)
phi[j]=phi[j]/i*(i-1);
}
ULL powMod(ULL a,ULL b,int c){
ULL ret=1;
a%=c;
while(b){
if(b&1) ret=ret*a%c;
a=a*a%c;
b/=2;
}
return ret;
}
int main(){
int t;
init();
scanf("%d",&t);
for(int ca=1;ca<=t;++ca){
ULL a,b,n,F1,F2;
int c,mod1,mod2,pos1,pos2;
scanf("%I64u%I64u%I64u%d",&a,&b,&n,&c);
fibb.clear();
fib1[1]=1%c;
fib1[2]=1%c;
fibb.insert(mp(mp(fib1[1],fib1[2]),2));
for(int i=3;i<=c*c+2;++i){
fib1[i]=(fib1[i-1]+fib1[i-2])%c;
if(!fibb.insert(mp(mp(fib1[i-1],fib1[i]),i)).second){
pos1=fibb[mp(fib1[i-1],fib1[i])];
mod1=i-pos1;
break;
}
}
fibb.clear();
fib2[1]=1%phi[c];
fib2[2]=1%phi[c];
fibb.insert(mp(mp(fib2[1],fib2[2]),2));
for(int i=3;i<=phi[c]*phi[c]+2;++i){
fib2[i]=(fib2[i-1]+fib2[i-2])%phi[c];
if(!fibb.insert(mp(mp(fib2[i-1],fib2[i]),i)).second){
pos2=fibb[mp(fib2[i-1],fib2[i])];
mod2=i-pos2;
break;
}
}
F2=powMod(fib2[powMod(a,b,mod2)+pos2-pos2%mod2],n-1,phi[c])+phi[c];
F1=fib1[powMod(a,b,mod1)+pos1-pos1%mod1];
//printf("%d %d\n",pos2,mod2);
//printf("%I64u\n",powMod(a,b,mod1)+pos1-pos1%mod1);
//printf("%I64u %I64u\n",F1,F2);
printf("Case %d: %I64u\n",ca,powMod(F1,F2,c));
}
return 0;
}