题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5667

题目意思:f1=1,i=1

     f2=2 ,i=2

     fi=a^b*f[i-1]^c*f[i-2] i>2

思路:发现a^b,和f[i-1]^c之类的东西,我们很明显吧这个幂变成乘,很自然的想到对数。问题是对什么取对数,最后发现对a取对数是合适的。

loga(fi)=loga(a^b*f[i-1]^c*f[i-2])=loga(a^b)+loga(f[i-1]^c)+loga(f[i-2]),我们设k[i]=loga(fi),所以k[i]=b+c*k[i-1]+k[i-2]。我们可以通过矩阵快速幂算出k[n],然后a^k[n]=f[n],可以直接用快速幂算出。

这里注意一下,由于k[n]非常大,所以为了使得a^k[n]%p==(a^(k[n]%y))%p,根据费马小定理如何gcd(a,p)=1,那么 a^(p-1)≡1(mod p),所以a^(p-1)%p=a^0%p,所以循环节为p-1,所以a^(k[n]%(p-1))%p。

这里还有注意一下如果a%p==0,a^(k[n]%(p-1))%p当k[n]=p-1的时候,a^(k[n]%(p-1))%p=1,但是实际上a^(k[n]%(p-1))%p=0,会造成错误,所以需要特判a%p==0的情况,不过这个题好像后台题目有点水,不必判断也能过貌似,所以代码里面没有体现

代码:

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL long long
LL p,aa,bb,cc,n,mod; //mod为p-1
struct matrix
{
LL mat[][];
};
matrix pow1(matrix a,matrix b) // N^3的矩阵相乘
{
matrix c;
memset(c.mat,,sizeof(c.mat));
for(int i=;i<;i++){
for(int j=;j<;j++){
for(int k=;k<;k++){
c.mat[i][j] += (a.mat[i][k]*b.mat[k][j]);
c.mat[i][j] %= mod;
}
}
}
return c;
}
matrix cheng(matrix a,LL y) //矩阵快速幂
{
matrix b;
memset(b.mat,,sizeof(b.mat));
for(int i=;i<;i++) b.mat[i][i] = ;
while(y){
if(y&){
b = pow1(a,b);
y-=;
}else {
a = pow1(a,a);
y/=;
}
}
return b;
}
LL quick_pow(LL a,LL tmp) //对a进行快速幂
{
LL b = 1ll;
while(tmp)
{
if(tmp&) b=(a*b)%p;
a=(a*a)%p;
tmp>>=;
}
return b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld%lld",&n,&aa,&bb,&cc,&p);
matrix ma;
mod = p-;
memset(ma.mat,,sizeof(ma.mat));//初始化递归矩阵
ma.mat[][] = cc; ma.mat[][] = ; ma.mat[][] = bb;
ma.mat[][] = ; ma.mat[][] = ; ma = cheng(ma,n-); //算指数和直接幂有点不同
LL tmp = ma.mat[][]*bb + ma.mat[][]; //取出指数
LL ans = quick_pow(aa,tmp);
printf("%lld\n",ans); }
return ;
}
05-11 19:38