传送门

Sol

考虑要求的东西的组合意义,问题转化为:

有 \(n\) 种小球,每种的大小为 \(a_i\),求选出大小总和为 \(m\) 的小球排成一排的排列数

有递推 \(f_i=\sum_{j=1}^{n}f_{i-a_j}\)

常系数线性递推

求一个满足 \(k\) 阶齐次线性递推数列 \(f_i\) 的第 \(n\) 项

\[f_n=\sum\limits_{i=1}^{k}a_i \times f_{n-i}
\]

给出 \(a_1...a_k\) 以及 \(f_0\)

\(k\) 为 \(10^5\) 级别,\(n\le 10^{18}\)

它的特征多项式为

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

如果 \(n\) 不是很大,可以直接对于 \(C(x)\) 求逆得到 \(f_1...f_n\)

否则

设向量 \(\alpha_i=(f_i,f_{i+1},...,f_{i+k-1})\)

设 \(f_i\) 的转移矩阵为 \(M\)

那么 \(\alpha_0M^n=\alpha_n\)

引入Cayley-Hamilton定理

把 \(M\) 看成 \(x\) 带入 \(P(x)\) 中,有 \(P(M)=0\) (全 \(0\) 矩阵)

所以有 \(\alpha_0M^n\equiv \alpha_n(mod~P(M))\)

如何求 \(P(x)\)

显然P(x)=C(x)

把 \(M\) 写出来

\[M=\begin{pmatrix}
0 & 0 & 0 & \cdots & 0 & 0 & a_{k} \\
1 & 0 & 0 & \cdots & 0 & 0 & a_{k-1} \\
0 & 1 & 0 & \cdots & 0 & 0 & a_{k-2} \\
\vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
0 & 0 & 0 & \cdots & 0 & 0 & a_{3} \\
0 & 0 & 0 & \cdots & 1 & 0 & a_{2} \\
0 & 0 & 0 & \cdots & 0 & 1 & a_{1}
\end{pmatrix}
\]

根据定义 \(P(x)=|xI-M|\),\(I\) 为单位矩阵

那么

\[xI-M=\begin{pmatrix}
x & 0 & 0 & \cdots & 0 & 0 & -a_{k} \\
-1 & x & 0 & \cdots & 0 & 0 & -a_{k-1} \\
0 & -1 & x & \cdots & 0 & 0 & -a_{k-2} \\
\vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
0 & 0 & 0 & \cdots & x & 0 & -a_{3} \\
0 & 0 & 0 & \cdots & -1 & x & -a_{2} \\
0 & 0 & 0 & \cdots & 0 & -1 & x-a_{1}
\end{pmatrix}
\]

按照最后一列展开得到

\(P(x)=x^k-a_1x^{k-1}-a_2x^{k-2}-\cdots-a_k=C(x)\)

所以只要多项式倍增快速幂 \(+\) 取模就好了(听起来就慢)

最后

\[\alpha_n=\alpha_0\sum_{i=0}^{k-1}g_iM^i=\sum_{i=0}^{k-1}g_i\alpha_i
\]

所以有

\[f_n=\sum_{i=0}^{k-1}g_if_i
\]

\(\Theta(k)\) 计算即可

注意多项式倍增快速幂的时候取模的多项式是一样的,可以预处理出它的逆

解决

套常系数线性递推的方法即可,前面 \(23333\) 项可以预处理求逆得到

  1. # include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int mod(104857601);
  5. const int maxn(1 << 16);
  6. inline int Pow(ll x, int y) {
  7. register ll ret = 1;
  8. for (; y; y >>= 1, x = x * x % mod)
  9. if (y & 1) ret = ret * x % mod;
  10. return ret;
  11. }
  12. inline void Inc(int &x, const int y) {
  13. if ((x += y) >= mod) x -= mod;
  14. }
  15. namespace FFT {
  16. int a[maxn], b[maxn], len, r[maxn], l, w[2][maxn];
  17. inline void Init(const int n) {
  18. register int i, x, y;
  19. for (l = 0, len = 1; len < n; len <<= 1) ++l;
  20. for (i = 0; i < len; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
  21. for (i = 0; i < len; ++i) a[i] = b[i] = 0;
  22. w[1][0] = w[0][0] = 1, x = Pow(3, (mod - 1) / len), y = Pow(x, mod - 2);
  23. for (i = 1; i < len; ++i) w[0][i] = (ll)w[0][i - 1] * x % mod, w[1][i] = (ll)w[1][i - 1] * y % mod;
  24. }
  25. inline void NTT(int *p, const int opt) {
  26. register int i, j, k, wn, t, x, y;
  27. for (i = 0; i < len; ++i) if (r[i] < i) swap(p[r[i]], p[i]);
  28. for (i = 1; i < len; i <<= 1)
  29. for (t = i << 1, j = 0; j < len; j += t)
  30. for (k = 0; k < i; ++k) {
  31. wn = w[opt == -1][len / t * k];
  32. x = p[j + k], y = (ll)wn * p[i + j + k] % mod;
  33. p[j + k] = x + y >= mod ? x + y - mod : x + y;
  34. p[i + j + k] = x - y < 0 ? x - y + mod : x - y;
  35. }
  36. if (opt == -1) for (wn = Pow(len, mod - 2), i = 0; i < len; ++i) p[i] = (ll)p[i] * wn % mod;
  37. }
  38. inline void Calc1() {
  39. register int i;
  40. NTT(a, 1), NTT(b, 1);
  41. for (i = 0; i < len; ++i) a[i] = (ll)a[i] * b[i] % mod;
  42. NTT(a, -1);
  43. }
  44. inline void Calc2() {
  45. register int i;
  46. NTT(a, 1), NTT(b, 1);
  47. for (i = 0; i < len; ++i) a[i] = (ll)a[i] * b[i] % mod * b[i] % mod;
  48. NTT(a, -1);
  49. }
  50. }
  51. struct Poly {
  52. vector <int> v;
  53. inline Poly() {
  54. v.resize(1);
  55. }
  56. inline Poly(const int d) {
  57. v.resize(d);
  58. }
  59. inline int Length() const {
  60. return v.size();
  61. }
  62. inline Poly operator +(Poly b) const {
  63. register int i, l1 = Length(), l2 = b.Length(), l3 = max(l1, l2);
  64. register Poly c(l3);
  65. for (i = 0; i < l1; ++i) c.v[i] = v[i];
  66. for (i = 0; i < l2; ++i) Inc(c.v[i], b.v[i]);
  67. return c;
  68. }
  69. inline Poly operator -(Poly b) const {
  70. register int i, l1 = Length(), l2 = b.Length(), l3 = max(l1, l2);
  71. register Poly c(l3);
  72. for (i = 0; i < l1; ++i) c.v[i] = v[i];
  73. for (i = 0; i < l2; ++i) Inc(c.v[i], mod - b.v[i]);
  74. return c;
  75. }
  76. inline void InvMul(Poly b) {
  77. register int i, l1 = Length(), l2 = b.Length(), l3 = l1 + l2 - 1;
  78. FFT :: Init(l3);
  79. for (i = 0; i < l1; ++i) FFT :: a[i] = v[i];
  80. for (i = 0; i < l2; ++i) FFT :: b[i] = b.v[i];
  81. FFT :: Calc2();
  82. }
  83. inline Poly operator *(Poly b) const {
  84. register int i, l1 = Length(), l2 = b.Length(), l3 = l1 + l2 - 1;
  85. register Poly c(l3);
  86. FFT :: Init(l3);
  87. for (i = 0; i < l1; ++i) FFT :: a[i] = v[i];
  88. for (i = 0; i < l2; ++i) FFT :: b[i] = b.v[i];
  89. FFT :: Calc1();
  90. for (i = 0; i < l3; ++i) c.v[i] = FFT :: a[i];
  91. return c;
  92. }
  93. inline Poly operator *(int b) const {
  94. register int i, l = Length();
  95. register Poly c(l);
  96. for (i = 0; i < l; ++i) c.v[i] = (ll)v[i] * b % mod;
  97. return c;
  98. }
  99. inline int Calc(const int x) {
  100. register int i, ret = v[0], l = Length(), now = x;
  101. for (i = 1; i < l; ++i) Inc(ret, (ll)now * v[i] % mod), now = (ll)now * x % mod;
  102. return ret;
  103. }
  104. };
  105. inline void Inv(Poly p, Poly &q, int len) {
  106. if (len == 1) {
  107. q.v[0] = Pow(p.v[0], mod - 2);
  108. return;
  109. }
  110. Inv(p, q, len >> 1);
  111. register int i;
  112. p.InvMul(q);
  113. for (i = 0; i < len; ++i) q.v[i] = ((ll)2 * q.v[i] + mod - FFT :: a[i]) % mod;
  114. }
  115. inline Poly Inverse(Poly a) {
  116. register int n = a.Length(), len;
  117. for (len = 1; len < n; len <<= 1);
  118. register Poly c(len);
  119. Inv(a, c, len), c.v.resize(a.Length());
  120. return c;
  121. }
  122. Poly invc;
  123. inline Poly operator %(const Poly &a, const Poly &b) {
  124. if (a.Length() < b.Length()) return a;
  125. register Poly x = a, y = invc;
  126. register int n = a.Length(), m = b.Length(), res = n - m + 1;
  127. reverse(x.v.begin(), x.v.end());
  128. x.v.resize(res), y.v.resize(res), x = x * y, x.v.resize(res);
  129. reverse(x.v.begin(), x.v.end()), y = a - x * b, y.v.resize(m - 1);
  130. return y;
  131. }
  132. int n, k = 23333, f[maxn], a[maxn], ans;
  133. ll m;
  134. Poly c, trs, tmp;
  135. int main() {
  136. register int i, sa, sb, v;
  137. scanf("%d%lld%d%d%d", &n, &m, &v, &sa, &sb), sa %= k, sb %= k;
  138. for (++a[v], i = 2; i <= n; ++i) ++a[v = (v * sa + sb) % k + 1];
  139. c.v.resize(k + 1), c.v[k] = 1;
  140. for (i = 1; i <= k; ++i) c.v[k - i] = (mod - a[i]) % mod;
  141. tmp.v.resize(2), trs.v.resize(1), trs.v[0] = tmp.v[1] = 1;
  142. invc = c, reverse(invc.v.begin(), invc.v.end()), invc = Inverse(invc);
  143. for (i = 0; i < k; ++i) f[i] = invc.v[i];
  144. if (m < k) return printf("%d\n", f[m]), 0;
  145. for (; m; m >>= 1, tmp = tmp * tmp % c) if (m & 1) trs = trs * tmp % c;
  146. for (i = 0; i < k; ++i) Inc(ans, (ll)trs.v[i] * f[i] % mod);
  147. printf("%d\n", ans);
  148. return 0;
  149. }

51nod1538:一道难题(常系数线性递推/Cayley-Hamilton定理)的更多相关文章

  1. 【BZOJ4944】【NOI2017】泳池 概率DP 常系数线性递推 特征多项式 多项式取模

    题目大意 有一个\(1001\times n\)的的网格,每个格子有\(q\)的概率是安全的,\(1-q\)的概率是危险的. 定义一个矩形是合法的当且仅当: 这个矩形中每个格子都是安全的 必须紧贴网格 ...

  2. [51nod1538]一道难题

    先观察一下题目给出的式子:对所有满足$\begin{align*}\sum\limits_{i=1}^na_ib_i=m\end{align*}$的$b_{1\cdots n}$,计算$\begin{ ...

  3. LG4723 【模板】常系数线性递推

    P4723 [模板]常系数齐次线性递推 题目描述 求一个满足$k$阶齐次线性递推数列${a_i}$的第$n$项. 即:$a_n=\sum\limits_{i=1}^{k}f_i \times a_{n ...

  4. HDU 2045 LELE的RPG难题(递推)

    不容易系列之(3)—— LELE的RPG难题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  5. 【图灵杯 F】一道简单的递推题(矩阵快速幂,乘法模板)

    Description 存在如下递推式: F(n+1)=A1*F(n)+A2*F(n-1)+-+An*F(1) F(n+2)=A1*F(n+1)+A2*F(n)+-+An*F(2) - 求第K项的值对 ...

  6. [原]hdu2045 不容易系列三——LELE的RPG难题 (递推方程)

    本文出自:blog.csdn.net/svitter 原题:http://acm.hdu.edu.cn/showproblem.php?pid=2045 题意:中文不用我说了吧. 这个题目的关键就在于 ...

  7. 【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP

    题目大意 一行有\(n\)个球,现在将这些球分成\(k\) 组,每组可以有一个球或相邻两个球.一个球只能在至多一个组中(可以不在任何组中).求对于\(1\leq k\leq m\)的所有\(k\)分别 ...

  8. Eddy's AC难题--hdu2200(递推)

    Problem Description Eddy是个ACMer,他不仅喜欢做ACM题,而且对于Ranklist中每个人的ac数量也有一定的研究,他在无聊时经常在纸上把Ranklist上每个人的ac题目 ...

  9. Cayley-Hamilton定理与矩阵快速幂优化、常系数线性递推优化

    原文链接www.cnblogs.com/zhouzhendong/p/Cayley-Hamilton.html Cayley-Hamilton定理与矩阵快速幂优化.常系数线性递推优化 引入 在开始本文 ...

随机推荐

  1. springBoot整合MyBatise及简单应用

    springBoot整合MyBatise及简单应用 我采用的是 工具IDEA 框架是springBoot+maven+Mybatise 第一步: pom.xml 引入相关jar包 <?xml v ...

  2. eclipse远程debug服务器上的项目(Tomcat),打开、关闭及常见错误汇总

    我们工作中,有时候测试/生产环境,出现的结果会与我们预计的不一样,只看代码又看不出去问题所在,这个时候就需要远程debug下服务器上的项目. 注意:(1)需要debug的代码,本机代码需与服务器上一致 ...

  3. redhat基本操作

     实验:安装redhat   需求:使用DVD镜像文件rhel-server-6.5-x86_64-dvd.iso,在虚拟机中安装RHEL 6系统 分区方案选择“使用所有空间”. 软件组选择“基本服务 ...

  4. localhost, 127.0.0.1, 0.0.0.0

    总结: localhost:是一个域名.域名可以认为是某个ip的别称,便于记忆.通常localhost对应的ip是127.0.0.1,不过这个也可以设置,参见知乎回答 127.0.0.1:是一个回环地 ...

  5. 2. 需要对测试用的数据进行MD5加密

    import hashlib phone_num = open("D:/testdata/phone10.txt","r") out_file = open(& ...

  6. 接口测试-postman,JMeter与LoadRunner比较

    postman是一个谷歌出的轻量级的专门测试接口的小工具~(PS:postman包括两种:Chrome浏览器插件和postman客户端,我使用的是postman客户端)虽然不如firefox的post ...

  7. P3440 [POI2006]SZK-Schools

    传送门 应该是很显然的费用流模型吧... $S$ 向所有学校连边,流量为 $1$,费用为 $0$(表示每个学校要选一个编号) 学校向范围内的数字连边,流量为 $1$,费用为 $c|m-m'|$(表示学 ...

  8. 华南理工大学“三七互娱杯”程序设计竞赛 HRY and codefire(概率期望DP)

    https://ac.nowcoder.com/acm/contest/874/A 题目:有两个账号 , 一开始都为0级 , 求任意一个账号升级到N的期望 要求:如果当前账号嬴了 , 就继续沿用当前的 ...

  9. smtp自动发送邮件demo

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...

  10. service iptables xxx无效命令的情况下,如何启动/重启iptables

    最近在CentOS 7.6下使用service iptables xxx相关命令,提示如下错误:The service command supports only basic LSB actions ...