传送门:hdu5667 Sequence
题意就是根据求f(n)%p
思路:列了一下前几项,然后找了一下规律……
f(1)=(a^b)^0
f(2)=(a^b)^1
f(3)=(a^b)^(1+c*1+0)
f(4)=(a^b)^(1+c*(1+c)+1)
这样就很容易看出来幂次是有规律的,如果设幂次g(n),那么g(1)=0,g(2)=1,g(3)=1+c*1+0,g(4)=1+c*(1+c)+1
g(n)=c*g(n-1)+g(n-2)+1
根据递推关系就可以构造矩阵啦
g(n) c 1 1 g(n-1) c 1 1 ^(n-2) g(2)
g(n-1) = 1 0 0 * g(n-2) = 1 0 0 * g(1)
1 0 0 1 1 0 0 1 1
但是如果这样计算,幂次会变得很大很大很大很大,所以要尽量降幂次
由于p给定了是一个素数,所以可以用公式a^n%p=a^(n%phi(p)+phi(p))%p
这样在计算g(n)的时候每次都对phi(p)取模再加上phi(p)就可以了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=3;
ll mod;
struct matrix
{
ll p[N][N];
};
ll phi(ll a)
{
ll ans=a;
for(ll i=2;i*i<=a;i++)
{
if(a%i==0)
{
ans=ans-ans/i;
while(a%i==0)
{
a/=i;
}
}
}
if(a>1)
{
ans=ans-ans/a;
}
return ans;
}
matrix matrix_mul(matrix a,matrix b)
{
int i,j,k;
matrix d;
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
d.p[i][j]=0;
for(k=0; k<N; k++)
{
d.p[i][j]+=(a.p[i][k]*b.p[k][j])%phi(mod)+phi(mod);
}
d.p[i][j]=d.p[i][j]%phi(mod)+phi(mod);
}
}
return d;
}
matrix matrix_pow(ll c,ll b)
{
matrix d= {1,0,0,
0,1,0,
0,0,1};
matrix temp= {c,1,1,
1,0,0,
0,0,1};
while(b)
{
if(b&1)
{
d=matrix_mul(d,temp);
}
b>>=1;
temp=matrix_mul(temp,temp);
}
return d;
}
ll quick_pow(ll a,ll b,ll m)
{
ll d=1;
while(b)
{
if(b&1)
{
d=d*a%m;
}
b>>=1;
a=a*a%m;
}
return d;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n,a,b,c;
scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&mod);
if(n==1) printf("1\n");
else
{
matrix tmp=matrix_pow(c,n-2);
ll pow=tmp.p[0][0]+tmp.p[0][2];
pow=pow%phi(mod)*b%phi(mod)+phi(mod);
a=a%mod;
ll ans=quick_pow(a,pow,mod);
printf("%lld\n",ans%mod);
}
}
return 0;
}