矩阵快速幂解线性递推式:
an=an−1+an−3 a_{n}=a_{n-1}+a_{n-3} an=an−1+an−3
Solution:
一般构造矩阵的时候都构造一个连续的矩阵,且这个矩阵元素下标都+1+1+1后两个矩阵恰好覆盖了递推式所涉及的所有项,设递推式跨越的下标长度为lenlenlen,这个长度一般是len−1len-1len−1,譬如当前构造矩阵
[an,an−1,an−2]
[a_{n},a_{n-1},a_{n-2}]
[an,an−1,an−2]
我们需要构造出一个矩阵,使得这个上式矩阵乘构造矩阵后得到
[an+1,an,an−1]
[a_{n+1},a_{n},a_{n-1}]
[an+1,an,an−1]
矩阵乘法:
对于两个矩阵a,ba,ba,b相乘,结果矩阵的iii行jjj列为
∑k=1nai,kbk,j \sum_{k=1}^{n}a_{i,k}b_{k,j} k=1∑nai,kbk,j
即aaa的iii行与bbb的jjj列的所有元素对应相乘相加单位矩阵:
是主对角线元素为111,其余元素为000的矩阵,即满足下式的矩阵
ai,j={0i≠j1i=j a_{i,j}=\begin{cases} 0 & i\neq j\\ 1 & i=j \end{cases} ai,j={01i=ji=j
根据矩阵乘法的规则构造矩阵为
[110001100]
\left[
\begin{matrix}
1 & 1 & 0\\
0 & 0 & 1\\
1 & 0 & 0
\end{matrix}
\right]
⎣⎡101100010⎦⎤
对此矩阵快速幂即可
需要注意的是,单位矩阵是主对角线元素为111的矩阵,其他元素为000;而不是都是111的矩阵
// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
#include<map>
using namespace std;
using ll=long long;
const int N=1e6+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=1e9+7;
struct matrix
{
ll a[3][3];
void initial(){memset(a,0,sizeof(a));}
void build()
{
initial();
for(int i=0;i<3;i++) a[i][i]=1;
}
ll* operator[](int i) const {
return (ll*)&a[i][0];
}
matrix operator*(const matrix& x) const
{
matrix ret; ret.initial();
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++) ret[i][j]=(ret[i][j]+a[i][k]*x[k][j]%mod)%mod;
return ret;
}
};
matrix qpow(matrix a,ll b)
{
matrix ret,base=a; ret.build();
while(b)
{
if(b&1) ret=ret*base;
base=base*base;
b>>=1;
}
return ret;
}
int main()
{
matrix tmp={{
{1,1,0},
{0,0,1},
{1,0,0}
}},ans={{
{1,1,1},
{0,0,0},
{0,0,0}
}};
int t; cin>>t;
while(t--)
{
ll n; cin>>n;
if(n<=3) cout<<1<<'\n';
else cout<<(ans*qpow(tmp,n-3)).a[0][0]<<'\n';
}
return 0;
}
本文介绍了一种利用矩阵快速幂技巧来高效求解线性递推式an=an-1+an-3的解法,通过构造特定矩阵并进行幂运算,简化了递推问题的求解过程。
1829

被折叠的 条评论
为什么被折叠?



