zoukankan      html  css  js  c++  java
  • 常系数齐次线性递推

    常系数齐次线性递推

    要干啥

    已知

    [f[n]=sum_{i=1}^k C_if[n-i] ]

    (f[n])的值,(nle 10^9,kle 20000),答案取模。

    暴力做法

    如果复杂度(O(nk))允许的话,显然是可以直接(dp)转移的。
    (k)很小的时候,转移写成矩阵形式,假设转移矩阵为(M),可以得到:(displaystyle f[n]=f[0]*M^n),这里的(f)是向量的形式。
    复杂度为(O(k^3logn))

    所以到底要怎么做

    显然我们已知矩乘的时候是一个(n)维向量乘上转移矩阵得到了一个(n)维向量。
    考虑这个转移的特征方程:

    [x^k=sum_{i=1}^k C_ix^{k-i} ]

    把它移项之后我们定义为特征多项式(C(x))

    [C(x)=x^k-sum_{i=1}^k C_ix^{k-i} ]

    根据(Cayley–Hamilton)定理,得到(C(M)=0),即把(x)替换为转移矩阵(M),最终的结果是一个零矩阵。
    而我们要求的就是(M^n),因此,我们只需要知道(M^n mod C(M))的结果就好了。
    求解这个过程可以类似快速幂的倍增求解,复杂度是两个(log)
    假设最终求解出来的余数多项式为

    [G(x)=sum_{i=0}^{k-1}g_ix^i ]

    假设我们中间的向量为(A[i]),那么最终我们的答案向量可以写成:

    [egin{aligned} A[0]G(M)&=A[0]sum_{i=0}^{k-1}g_iM^i\ A[0]G(M)&=sum_{i=0}^{k-1}g_i(A[0]M^i)\ A[0]G(M)&=sum_{i=0}^{k-1}g_iA[i] end{aligned}]

    而事实上我们要求的并不是最终的向量(A[n]),而只有向量(A[n])的最后一项。
    因此:

    [f[n]=sum_{i=0}^{k-1}g_if[i] ]

    那么这样一来我们把矩阵的转移变成了简单的数之间的转移。
    时间复杂度为(O(klogklogn))

    似乎这篇文章里面有些细节上的东西写得不是很好,意会一下就好了。

  • 相关阅读:
    D. Constructing the Array
    B. Navigation System
    B. Dreamoon Likes Sequences
    A. Linova and Kingdom
    G. Special Permutation
    B. Xenia and Colorful Gems
    Firetrucks Are Red
    java getInstance()的使用
    java 静态代理和动态代理
    java 类加载机制和反射机制
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10152566.html
Copyright © 2011-2022 走看看