题目链接:​​Sequence​

题目大意:给你一个这样的公式,fn=⎧⎩⎨⎪⎪1,ab,abfcn−1fn−2,n=1n=2otherwise,然后求fn对p求余,给出n,a,b,c,p

题目思路:首先我们可以很轻松的构造出这样一个东西,这个fn一定是a的幂次,所以我们稍微推一下可知,对于fn,令他的幂系数为f(n),则f(n) = c*f(n-1)+f(n-2)+b,然后构造一下矩阵去计算这个系数,但是需要注意的是,这里算矩阵的时候不能够对MOD求余,而是对MOD-1求余,因为由费马小定理可知ab∗p[n]=ab∗p[n]mod(mod−1)%mod,所以我们矩阵快速幂的系数是对p-1求余,然后还需要去注意的一点是当a%p == 0时,需要特殊处理,比如3 4 3 2 2这组数据,不特殊处理会输出1,但是实际上应该输出0,手动模拟一下就好了

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;
const ll maxn = 4;
ll MOD;
#define mod(x) ((x)%MOD)

struct mat{
ll m[maxn][maxn];
}unit;

mat operator *(mat a,mat b){
mat ret;
ll x;
for(ll i = 0;i < maxn;i++){
for(ll j = 0;j < maxn;j++){
x = 0;
for(ll k = 0;k < maxn;k++)
x += mod((ll)a.m[i][k]*b.m[k][j]);
ret.m[i][j] = mod(x);
}
}
return ret;
}

void init_unit(){
for(ll i = 0;i < maxn;i++)
unit.m[i][i] = 1;
return ;
}

mat pow_mat(mat a,ll n){
mat ret = unit;
while(n){
if(n&1) ret = ret*a;
a = a*a;
n >>= 1;
}
return ret;
}

ll quick_pow(ll a,ll n){
ll ans = 1;
while(n){
if(n&1) ans = (ans*a)%MOD;
a = (a*a)%MOD;
n >>= 1;
}
return ans;
}

int main(){
ll n,A,B,C,P,T,ans;
init_unit();
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld%lld%lld",&n,&A,&B,&C,&P);
MOD = P;
if(n == 1ll) puts("1");
else if(n == 2ll) printf("%lld\n",quick_pow(A,B));
else{
if(A%P == 0) {printf("0\n");continue;}
mat a,b;
b.m[0][0] = C,b.m[0][1] = 1,b.m[0][2] = 0,b.m[0][3] = 0;
b.m[1][0] = 1,b.m[1][1] = 0,b.m[1][2] = 1,b.m[1][3] = 0;
b.m[2][0] = 0,b.m[2][1] = 0,b.m[2][2] = 0,b.m[2][3] = 0;
b.m[3][0] = 1,b.m[3][1] = 0,b.m[3][2] = 0,b.m[3][3] = 1;


a.m[0][0] = B,a.m[0][1] = 0,a.m[0][2] = 0,a.m[0][3] = B;
MOD--;
b = pow_mat(b,n-2);
a = a*b;
MOD++;
printf("%lld\n",quick_pow(A,a.m[0][0]));
}
}
return 0;
}