題目大意:就是給你兩個函數,一個是F(n) = F(n-1) + F(n-2),
F(0) = 0, F(1) = 1;
另一個是 G(n) = G(n-1)^F(a^b);
G(1) = F(a^b);
求G(n) % c;
範圍:A, B, N, C (10<=A, B<2^64, 2<=N<2^64, 1<=C<=300)
注意了:c的範圍是1<= C <= 300,所以說它一定會有循環 節:
解題思路: 首先算G(1) = F(a^b),設a^b的循環節是len;
F(a^b)%c = F(a^b%len)%c;
一邊加一邊取餘
然後算G(n)%c = F(a^b)^(F(a^b)^(n-1)) % c;
G(n)%c = F(a^b)^(F(a^b)^(n-1)%phi(c)+phi(c))%c;
F(a^b)^(n-1)%phi(c)+phi(c) == (F(a^b)%phi(c)^(n-1))+phi(c)
F(a^b)%phi(c) 有循環節
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#define ll unsigned long long
using namespace std;
ll f[90005];
ll power(ll a,ll b,ll mod)
{
ll ans=1;
a=a%mod; // !!注意
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll lala(ll n)
{
ll ans=n;
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);// φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn) 公式
while(n%i==0)
{
n/=i;
}
}
}
if(n>1)
ans=ans/n*(n-1);
return ans;
}
ll loop(ll m)
{
f[0]=0;
f[1]=1;
f[2]=1;
for(ll 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()
{
int t;
cin>>t;
int cnt=0;
while(t--)
{
ll a,b,n,c;
cin>>a>>b>>n>>c;
printf("Case %d: ",++cnt);
if(c==1)
{
cout<<0<<endl;
continue;
}
ll ph=lala(c);
ll l=loop(c);
ll cur=power(a,b,l);
cur=f[cur];
if(ph==1) // 歐拉值爲1時特判
{
cout<<power(cur,ph,c)<<endl;
continue;
}
l=loop(ph);
ll sum=power(a,b,l);
sum=f[sum];
sum=power(sum,n-1,ph)+ph;
cur=power(cur,sum,c);
cout<<cur<<endl;
}
return 0;
}