题目链接
题意:题目很容易理解,给出公式Fx = c^(2x-6)*Fx-1*Fx-2*Fx-3,然后给出n,c,F1,F2,F3,求Fn;
题解:看到这个公式就知道要套矩阵快速幂了。但这题比较特殊,要套两个矩阵快速幂。
1. 对于Fx
- F4 = F3 * F2 *F1;
- F5 = F3^2 * F2^2 * F1;
- F6 = F3^4 * F2^3 * F1^2;
- 到F7时,F7的F1,F2,F3幂次方就等于F4,F5,F6的F1,F2,F3幂次方相加。
- F7 = F3^7 * F2^6 * F1^4;
- 发现规律了吗?当推到F7项之后的递推式时,当前项的F1,F2,F3幂次方都等于前三项F1,F2,F3幂次方之和。
- 所以F1,F2,F3其实分别都对应了一个关系矩阵,只是他们的关系矩阵相同而已。
- 所以我们可以先求出这个关系矩阵,不同的只是带入的g1,g2,g3不同。
- 设函数gn为第n项的幂次方。
- 递推式gn = gn-1 + gn-2 + gn-3。
- 最后得到关系矩阵
2. 对于C^(2*x-6)
我们对这个函数的幂次方进行矩阵构造。
- F4 = C^2 = 2
- F5 = C^6 = 6
- F6 = C^14 = 14
- F7 = F4*F5*F6*C^8 = 2+6+14+8
- 所以得到递推式Gn = Gn-1 + Gn-2 + Gn-3 + 2*n - 6
- 这样就能很好的构造矩阵了
要注意这是对他们的幂次方进行的矩阵构造。所以我们可以采取欧拉降幂。
其次因为第二个关系矩阵里存在负数,所以在求和的过程中要采取 (ans+mod)%mod的形式,保证其为正数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,f1,f2,f3,k;
const int mod = 1e9+7-1;
ll powmod(ll a,ll b) {ll res=1;a%=(mod+1);
for(;b;b>>=1){if(b&1)res=res*a%(mod+1);a=a*a%(mod+1);}return res;}
struct mat{ll a[10][10];};
ll k1,k2,k3;
mat init(mat c,int len){//矩阵初始化
int b[4][4]={{1,1,1},
{1,0,0},
{0,1,0}};
int t[6][6]={{1,1,1,2,-4},
{1,0,0,0,0},
{0,1,0,0,0},
{0,0,0,1,1},
{0,0,0,0,1}};
for(int i=0;i<len;i++)
for(int j=0;j<len;j++)
if(len==3) c.a[i][j]=b[i][j];
else if(len==5) c.a[i][j]=t[i][j];
return c;
}
mat mat_mul(mat x,mat y,int len){//矩阵快速乘
mat res;
memset(res.a,0,sizeof res.a);
for(int i=0;i<len;i++)
for(int j=0;j<len;j++)
for(int k=0;k<len;k++)
res.a[i][j] = (x.a[i][k]*y.a[k][j]+res.a[i][j]+mod)%mod;//可能存在负数,所以要+mod
return res;
}
ll mat_pow(ll n,int len){//矩阵快速幂
mat c,res;
c = init(c,len);
ll m = n;
memset(res.a,0,sizeof res.a);
for(int i=0;i<len;i++) res.a[i][i] = 1;
for(;n;n>>=1){
if(n&1) res = mat_mul(res,c,len);
c = mat_mul(c,c,len);
}
if(len==3) {//第一个矩阵
k1=res.a[0][0];
k2=res.a[0][1];
k3=res.a[0][2];
}
if(len==5){//第二个矩阵
ll ans = (res.a[0][0]*14+res.a[0][1]*6+res.a[0][2]*2
+res.a[0][3]*6+res.a[0][4]+mod)%mod;//可能存在负数所以要+mod
return ans;//返回幂次方
}
return 1;
}
int main()
{
ll ans = 1;
ll p[5][5]={{1,1,1,2},
{2,2,1,6},
{4,3,2,14}};
cin>>n>>f1>>f2>>f3>>k;
if(n<=6){//n小于6时不能用矩阵快速幂
ans = (ans*powmod(f3,p[n-4][0]))%(mod+1);
ans = (ans*powmod(f2,p[n-4][1]))%(mod+1);
ans = (ans*powmod(f1,p[n-4][2]))%(mod+1);
ans = ans*powmod(k,p[n-4][3])%(mod+1);
}
else {
mat_pow(n-6,3);
ans = (ans*powmod(f3,(4*k1+2*k2+k3)%mod))%(mod+1);
ans = (ans*powmod(f2,(3*k1+2*k2+k3)%mod))%(mod+1);
ans = (ans*powmod(f1,(2*k1+1*k2+k3)%mod))%(mod+1);
ll t=mat_pow(n-6,5);
ans = ans*powmod(k,t%mod)%(mod+1);
}
cout<<ans<<endl;
}