• 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)


    这里所有的内容都将有关于一个线性递推:

    $f_{n} = sumlimits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k - 1}$是已知的。

    BM是用于求解线性递推式的工具,传入一个序列,会返回一个合法的线性递推式,一个$vector$,其中第$i$项表示上式的$a_{i + 1}$。

    CH用于快速求解常系数齐次线性递推的第$n$项,我们先会求出一个特征多项式$g$,$g$的第$k$项是$1$,其余项中第$k - i$项是$-a_{i}$。然后可以得到$c = x^{n} ; mod  ; g$这么一个多项式,最后的答案就是$sumlimits_{i = 0}^{k - 1} c_{i} * f_{i}$,这里用$c_{i}$表示$c$中第$i$项的系数。

    其实这里只是想给出两者的板子,素质二连:

    namespace BM{
    #define pb push_back
    #define SZ(x) ((int)x.size())
    #define REP(i, a, b) for (int i = a; i < b; ++i)
      LL Pow(LL x, LL b) {
        LL re = 1;
        x %= MOD, assert(b >= 0);
        for (; b; b >>= 1, x = x * x % MOD)
          if (b & 1) re = re * x % MOD;
        return re;
      }
      VI Bm(VI x) {
        VI ls, cur;
        int pn = 0, lf, ld;
        REP(i, 0, SZ(x)) {
          LL t = -x[i] % MOD;
          REP(j, 0, SZ(cur))
            t = (t + x[i - j - 1] * (LL)cur[j]) % MOD;
          if (!t) continue;
          if (cur.empty()) {
            cur.resize(i + 1);
            lf = i, ld = t;
            continue;
          }
          LL k = -t * Pow(ld, MOD - 2) % MOD;
          VI c(i - lf - 1);
          c.pb(-k);
          REP(j, 0, SZ(ls)) c.pb(ls[j] * k % MOD);
          if (c.size() < cur.size())
            c.resize(cur.size());
          REP(j, 0, SZ(cur))
            c[j] = (c[j] + cur[j]) % MOD;
          if (i - lf + SZ(ls) >= SZ(cur))
            ls = cur, lf = i, ld = t;
          cur = c;
        }
        VI &o = cur;
        REP(i, 0, SZ(o))
          o[i] = (o[i] % MOD + MOD) % MOD;
        return o;
      }
    }
    
    namespace CH {
    #define SZ(x) ((int)x.size())
      VI g;
      int k;
      inline void Ad(int &a, int b) {
        if ((a += b) >= MOD) a -= MOD;
      }
      VI Mul(VI a, VI b) {
        VI c;
        assert(SZ(a) <= k && SZ(b) <= k);
        c.resize(SZ(a) + SZ(b) - 1);
        for (int i = 0; i < SZ(a); ++i)
          for (int j = 0; j < SZ(b); ++j)
            Ad(c[i + j], (LL)a[i] * b[j] % MOD);
        for (int i = SZ(c) - 1; i >= k; --i)
          for (int j = 0; j <= k; ++j)
            Ad(c[i - k + j], MOD - (LL)c[i] * g[j] % MOD);
        c.resize(k);
        return c;
      }
      VI Solve(VI a, int n) {
        k = SZ(a);
        g.resize(k + 1, 1);
        for (int i = 1; i <= k; ++i)
          g[k - i] = (MOD - a[i - 1]) % MOD;
        VI re(1, 1), x(2, 1);
        x[0] = 0;
        for (; n; n >>= 1, x = Mul(x, x))
          if (n & 1) re = Mul(re, x);
        return re;
      }
    }
    View Code
  • 相关阅读:
    node.js mongodb笔记
    查询数据库的连接情况
    使用cmd命令查看电脑端口占用情况
    正则表达式基本语法
    ASCII码对照表
    使用命令实现IIS 站点和应用程序池自动启动和停止
    postgresql常见命令及操作
    apigateway-kong(四)负载均衡理论及实现
    apigateway-kong(三)Proxy规则
    apigateway-kong(二)admin-api(结合实例比官网还详细)
  • 原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/9810513.html
Copyright © 2020-2023  润新知