zoukankan      html  css  js  c++  java
  • bzoj4161 (k^2logn求线性递推式)

    分析:

      我们可以写把转移矩阵A写出来,然后求一下它的特征多项式,经过手动计算应该是这样的p(x)=$x^k-sumlimits_{i=1}^ka_i*x^{k-i}$

      根据Cayley-Hamilton定理可得,p(A)=0

      他表示$A^n = f(A) * p(A) + g(A)$

      第一项的值是0,所以即$A^n=g(A)$,其中f(A) g(A)都是关于A的多项式,f(A)是多项式除法的商,g(A)是余数

      我们考虑$x^n$这个多项式,我们去求出它对于$p(A)$的余数多项式$g(A)$,那么$A^n$就等价于了$g(A)$,注意到新的多项式次数就很低了,不超过k-1

      我们要求的是$A^nH=sumlimits_{i=0}^{k-1}c_i*A^i*H$的第一个元素,注意到$A^i*H$相当于把H又递推了i次

      所以结果等价于$A^nH=sumlimits_{i=0}^{k-1}c_i*A^i*H$

      时间复杂度$O(k^2 log n)$,但常数很大

      中间的多项式取模和递推可以用FFT来优化,但常数更巨大

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=4000,mod=1000000007;
     4 int a[maxn+5],p[maxn+5],ans[maxn+5],num[maxn+5];
     5 int h[maxn+5],tmp[maxn+5];
     6 int n,k;
     7 void mul(int *a,int *b,int *ans)
     8 {
     9     for(int i=0;i<=2*k;++i) tmp[i]=0;
    10     for(int i=0;i<k;++i)
    11         for(int j=0;j<k;++j)
    12             tmp[i+j]=(tmp[i+j]+1LL*a[i]*b[j])%mod;
    13     for(int i=2*k-2;i>=k;--i)
    14     {
    15         for(int j=k-1;j>=0;--j)
    16             tmp[i-k+j]=(tmp[i-k+j]-1LL*tmp[i]*p[j])%mod,tmp[i-k+j]=(tmp[i-k+j]+mod)%mod;
    17         tmp[i]=0;
    18     }
    19     for(int i=0;i<k;++i) ans[i]=tmp[i];
    20 }
    21 int main()
    22 {
    23     scanf("%d%d",&n,&k);
    24     for(int i=1;i<=k;++i) scanf("%d",&a[i]);
    25     for(int i=0;i<k;++i) scanf("%d",&h[i]);
    26     p[k]=1;
    27     for(int i=1;i<=k;++i) p[k-i]=mod-a[i];
    28     for(int i=k;i<2*k;++i)
    29         for(int j=1;j<=k;++j)
    30         {
    31             h[i]=h[i]+1LL*h[i-j]*a[j]%mod;
    32             h[i]%=mod;
    33         }
    34     if(n<2*k) return 0*printf("%d
    ",h[n]);
    35     int b=n-k+1;
    36     num[1]=1,ans[0]=1;
    37     while(b)
    38     {
    39         if(b&1) mul(ans,num,ans);
    40         mul(num,num,num);
    41         b>>=1;
    42     }
    43     long long res=0;
    44     for(int i=0;i<k;++i) res=(res+1LL*ans[i]*h[i+k-1])%mod;
    45     printf("%lld
    ",(res+mod)%mod);
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    每日博客
    每日博客
    每日博客
    每日博客
    每日博客
    每日博客
    每日博客
    每日博客
    centos7 systemctl 管理MySQL
    Postgresqlz之迁移数据pg_dump
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8449176.html
Copyright © 2011-2022 走看看