题意:
给出题意中那么个函数,给出a、b、p、n,求函数调用的次数(mod p)。
思路:
能很容易看出来a和b的阶数是斐波那契数,n过大,用矩阵快速幂求斐波那契数,然后用欧拉函数进行取模的优化。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1000050
long long a,b,n,p;
long long minDiv[maxn],phi[maxn],sum[maxn];
void genphi()
{
for(long long i=1; i<maxn; i++)
{
minDiv[i]=i;
}
for(long long i=2; i*i<maxn; i++)
{
if(minDiv[i]==i)
{
for(long long j=i*i; j<maxn; j+=i)
{
minDiv[j]=i;
}
}
}
phi[1]=1;
for(long long i=2; i<maxn; i++)
{
phi[i]=phi[i/minDiv[i]];
if((i/minDiv[i])%minDiv[i]==0)
{
phi[i]*=minDiv[i];
}
else
{
phi[i]*=minDiv[i]-1;
}
}
return ;
}
struct matrix
{
long long A[2][2];
};
long long Phi;
matrix power(matrix ans1,matrix ans2)
{
int i,j,k;
matrix ans;
for(i=0; i<=1; i++)
{
for(j=0; j<=1; j++)
{
ans.A[i][j]=0;
for(k=0; k<=1; k++)
{
ans.A[i][j]+=ans1.A[i][k]*ans2.A[k][j];
if(ans.A[i][j]>Phi)
{
ans.A[i][j]=ans.A[i][j]%Phi+Phi;
}
}
}
}
return ans;
}
matrix mod(matrix un,long long k)
{
matrix ans;
ans.A[0][0]=1;
ans.A[0][1]=0;
ans.A[1][0]=0;
ans.A[1][1]=1;
while(k)
{
if(k%2) ans=power(ans,un);
un=power(un,un);
k/=2;
}
return ans;
}
long long pow_mod(long long a,long long k)
{
long long ans;
ans=1;
while(k)
{
if(k%2)
{
ans=ans*a;
ans%=p;
}
a=a*a;
a%=p;
k/=2;
}
return ans%p;
}
int main()
{
genphi();
//printf("%lld\n",phi[100015]);
int t;
int cas=1;
//for(int i=1;i<=13;i++)
// printf("%d %lld\n",i,phi[i]);
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld",&a,&b,&p,&n);
printf("Case #%d: ",cas++);
if(n==1)
{
printf("%lld\n",a%p);
continue;
}
else if(n==2)
{
printf("%lld\n",b%p);
continue;
}
else if(n==3)
{
printf("%lld\n",a*b%p);
continue;
}
matrix init;
init.A[0][0]=0;
init.A[0][1]=1;
init.A[1][0]=1;
init.A[1][1]=1;
//printf("%lld\n",phi[1]);
Phi=phi[p];
//printf("%lld\n",Phi);
matrix zhi=mod(init,n-3);
long long azhi=zhi.A[1][1];
long long bzhi=zhi.A[0][1]+zhi.A[1][1];
if(bzhi>Phi)
bzhi=bzhi%Phi+Phi;
long long aa1=pow_mod(a,azhi);
long long aa2=pow_mod(b,bzhi);
printf("%lld\n",aa1*aa2%p);
}
return 0;
}