【BZOJ4161】Shlw loves matrixI

题目描述

给定数列 {hn}前k项,其后每一项满足
hn = a1h(n-1) + a2h(n-2) + ... + ak*h(n-k)
其中 a1,a2...ak 为给定数列。请计算 h(n),并将结果对 1000000007 取模输出。

解法

一个显然的思路就是矩阵乘法,但这样的话显然超时。
实际上,我们还可以继续对这个矩阵乘法进行优化。

首先,由于这是常系数齐次线性递推式,简单来说就是:
\[f_i=\sum_{j=1}^k a_i*f_{i-j}\]
然后,我们需要引进特征多项式这个概念。
对于一个矩阵\(A\),它的特征多项式是\(f(x)=|Ix-A|\)
把行列式展开之后得,\(f(x)=|Ix-A|=x^K-\sum_{i=1}^K a_i*x^{K-i}\)
由Cayley-hamilton定理,那么我们知道\(f(A)=0\)
然后就能知道一个关键的式子:
\[A^K=\sum_{i=1}^K a_i*A^{K-i}\]

然后由于\(A^i\)都能表示成\(A^1,A^2,....,A^K\)的线性组合,
所以现在矩阵乘法直接使用\(O(K^2)\)的卷积即可。

当得到了\(A^n=\sum_{i=1}^K c_i*A^i\)之后,我们乘上题目给的向量h。
那么就会有\(\sum_{i=1}^K c_i*A^i*h_K\),即\(Ans=\sum_{i=1}^K c_i*h_{K+i}\)

复杂度就被优化为\(O(K^2 log n)\)

Code

#include<bits/stdc++.h>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;

const int maxn=4007,mo=1e9+7;

int n,K;
int a[maxn],h[maxn],f[maxn];
int Ans;

void Init(){
    scanf("%d%d",&n,&K);
    fo(i,1,K) scanf("%d",&a[i]);
    memcpy(f,a,sizeof a);
    fo(i,1,K) scanf("%d",&h[i]);
}

#define PLUS(x,y) (x)=((x)+(y))%mo
void mult(int *a,int *b){
    static int c[maxn];
    memset(c,0,sizeof c);
    fo(i,1,K)
        fo(j,1,K)
            PLUS(c[i+j],1ll*a[i]*b[j]);
    fd(i,2*K,K+1)
        fo(j,1,K)
            PLUS(c[i-j],1ll*c[i]*f[j]);
    memcpy(a,c,sizeof c);
}

void qPower(int x){
    bool bz=false;
    static int b[maxn];
    b[1]=1;
    while (x){
        if (x&1){
            if (bz) mult(a,b);
            else{
                bz=true;
                memcpy(a,b,sizeof b);
            }
        }
        mult(b,b);
        x>>=1;
    }
}
void Solve(){
    n++;
    fo(i,K+1,2*K) fo(j,1,K) PLUS(h[i],1ll*h[i-j]*a[j]);
    if (n<=2*K){
        Ans=h[n];
        return;
    }
    qPower(n-K);
    Ans=0;
    fo(i,1,K) PLUS(Ans,1ll*a[i]*h[i+K]);
}

void Print(){
    Ans=(Ans+mo)%mo;
    printf("%d\n",Ans);
}

int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    Init();
    Solve();
    Print();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hiweibolu/p/9163482.html