矩阵快速幂模板
和快速幂模板原理一样
struct node {
ll mat[15][15];//定义矩阵
}x,y;
int le;
void init(node &ans){
memset(ans.mat,0,sizeof(ans.mat));
for(int i=0;i<le;i++)
ans.mat[i][i]=1;
}
node mul(node x,node y){
node ans;
for(int i=0;i<le;i++)
for(int j=0;j<le;j++){
ans.mat[i][j]=0;
for(int k=0;k<le;k++)
ans.mat[i][j]+=(x.mat[i][k]*y.mat[k][j])%mod;
ans.mat[i][j]%=mod;
}
return ans;
}
node matpow(node s,ll m){
node ans;
init(ans);
while(m){
if(m&1)
ans=mul(ans,s);
m>>=1;
s=mul(s,s);
}
return ans;
}
题目引入
传送门
题意:一看就是一个裸的矩阵快速幂。
f[n] = 2*f[n-2] + f[n-1] + i^3
构造矩阵 (偷来的方法 )
推导过程
左边对应的公式乘上对应每行得到右面
参数增加,所以要增加维度
补齐
最后f[n] = A^(n-2) * res
初始矩阵为res = {a2,a1,3^3 , 3^2,3,1} = {2,1,27,9,3,1}。
贴上代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 123456789;
struct node {
ll mat[15][15];//定义矩阵
}x,y;
int le;
void init(node &ans){
memset(ans.mat,0,sizeof(ans.mat));
for(int i=0;i<le;i++)
ans.mat[i][i]=1;
}
node mul(node x,node y){
node ans;
for(int i=0;i<le;i++)
for(int j=0;j<le;j++){
ans.mat[i][j]=0;
for(int k=0;k<le;k++)
ans.mat[i][j]+=(x.mat[i][k]*y.mat[k][j])%mod;
ans.mat[i][j]%=mod;
}
return ans;
}
node matpow(node s,ll m){
node ans;
init(ans);
while(m){
if(m&1)
ans=mul(ans,s);
m>>=1;
s=mul(s,s);
}
return ans;
}
void solve(ll n){
node a;
a.mat[0][0] = 1,a.mat[0][1] = 2,a.mat[0][2] = 1,a.mat[0][3] = 0,a.mat[0][4] = 0,a.mat[0][5] = 0;
a.mat[1][0] = 1,a.mat[1][1] = 0,a.mat[1][2] = 0,a.mat[1][3] = 0,a.mat[1][4] = 0,a.mat[1][5] = 0;
a.mat[2][0] = 0,a.mat[2][1] = 0,a.mat[2][2] = 1,a.mat[2][3] = 3,a.mat[2][4] = 3,a.mat[2][5] = 1;
a.mat[3][0] = 0,a.mat[3][1] = 0,a.mat[3][2] = 0,a.mat[3][3] = 1,a.mat[3][4] = 2,a.mat[3][5] = 1;
a.mat[4][0] = 0,a.mat[4][1] = 0,a.mat[4][2] = 0,a.mat[4][3] = 0,a.mat[4][4] = 1,a.mat[4][5] = 1;
a.mat[5][0] = 0,a.mat[5][1] = 0,a.mat[5][2] = 0,a.mat[5][3] = 0,a.mat[5][4] = 0,a.mat[5][5] = 1;
a = matpow(a,n);
ll ans = (a.mat[0][0]*2%mod+a.mat[0][1]%mod+a.mat[0][2]*27%mod+a.mat[0][3]*9%mod+a.mat[0][4]*3%mod+a.mat[0][5]%mod)%mod;
printf("%lld\n",ans);
}
int main(){
int t;
scanf("%d",&t);
ll n;
le = 6;
while(t--){
scanf("%lld",&n);
solve(n-2);
}
return 0;
}