题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5667;
题意:给出一个递推式求解fn的值。
分析:因为是递推,很容易联想到矩阵快速幂。但本题的式子是一个乘法,所以就采用求对数然后就变成加法了。当然本题求完对数后腰用费尔马小定理来求解a的b次方,因为求对数,最后还要求回指数。本题求完对数的公式为f(n)=(b+f(n-1)*c+f(n-2))mod p-1;f1=0;f2=b;
最终结果为 a^(f(n))%p;
代码如下:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
struct Matrax{
long long m[10][10];
}ter;
long long mod;
Matrax muli(Matrax a,Matrax b){
Matrax p;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++){
p.m[i][j]=0;
for(int k=0;k<3;k++){
p.m[i][j]+=(a.m[i][k]*b.m[k][j])%(mod-1);
p.m[i][j]%=mod-1;
}
}
return p;
}//矩阵乘法
Matrax quick_mod(Matrax a,long long b){
Matrax ans=ter;
while(b){
if(b&1){
ans=muli(ans,a);
b--;
}
else {
b>>=1;
a=muli(a,a);
}
}
return ans;
}//快速幂
long long qmod(long long a,long long b){
long long ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
b--;
}
b>>=1;
a=a*a%mod;
}
return ans;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
long long n,a,b,c;
scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&mod);
if(n==1){
puts("1");
continue;
}
if(n==2){
printf("%I64d\n",qmod(a,b));
continue;
}
ter.m[0][0]=1;
ter.m[0][1]=0;
ter.m[0][2]=0;
ter.m[1][0]=0;
ter.m[1][1]=1;
ter.m[1][2]=0;
ter.m[2][0]=0;
ter.m[2][1]=0;
ter.m[2][2]=1;//初始化E矩阵 因为本题推出来是三元相加,所以用三维矩阵
n-=2;
Matrax A,B;
A.m[0][0]=0;
A.m[0][1]=1;
A.m[0][2]=0;
A.m[1][0]=1;
A.m[1][1]=c;
A.m[1][2]=0;
A.m[2][0]=0;
A.m[2][1]=b;
A.m[2][2]=1;//这里是中间连乘部分的矩阵
A=quick_mod(A,n);
B.m[0][0]=0;
B.m[0][1]=b;
B.m[0][2]=1;
B.m[1][0]=0;
B.m[1][1]=0;
B.m[1][2]=0;
B.m[2][0]=0;
B.m[2][1]=0;
B.m[2][2]=0;
B=muli(B,A);//这里是最初始的矩阵
// cout<<B.m[0][1]<<endl;
// cout<<a<<endl;
printf("%I64d\n",qmod(a,B.m[0][1]+mod-1));
}
return 0;
}