洛谷题库 P6031 Cards 加强版 – 题解与思路重现

洛谷题库 P6031 Cards 加强版

对于每一轮对局的 m!m! 种排列,对于编号为 aa 的牌,恒有 (m1)!(m-1)! 种是以牌 aa 为首的。因此一轮可以归为 mm 种情况,首张为王牌的概率为 1m\frac{1}{m}

这是某场模拟考试给出的部分分: SubtaskConstraintsPointsDependencies1n,m,k522k=123k5000101,24m1001015nk56k105101,2,37k5×106201,2,3,684117 \begin{array}{cccc} \text{Subtask}&\text{Constraints}&\text{Points}&\text{Dependencies}\\ \hline 1&n,m,k\leq 5&2&\\ 2&k=1&2&\\ 3&k\leq 5000&10&1,2\\ 4&m\leq 100&10&1\\ 5&n\leq k&5&\\ 6&k\leq 10^5&10&1,2,3\\ 7&k\leq 5\times 10^6&20&1,2,3,6\\ 8&&41&1\sim 7 \end{array}

部分分

我首先考虑的是期望的线性性

En(xk)E_n(x^k) 为洗牌 nn 次,获胜场次的 kk 次方的期望。考虑下一场的胜负情况。对于 n>0n>0,有转移 En(xk)=m1mEn1(xk)+1mEn1((x+1)k)=m1mEn1(xk)+1mEn1(i=0k(ki)xi)=m1mEn1(xk)+1mi=0k(ki)En1(xi)=En1(xk)+1mi=0k1(ki)En1(xi)\begin{aligned} E_n(x^k)&=\frac{m-1}{m}E_{n-1}(x^k)+\frac{1}{m}E_{n-1}\left((x+1)^k\right)\\ &=\frac{m-1}{m}E_{n-1}(x^k)+\frac{1}{m}E_{n-1}\left(\sum_{i=0}^k\binom{k}{i}x^i\right)\\ &=\frac{m-1}{m}E_{n-1}(x^k)+\frac{1}{m}\sum_{i=0}^k\binom{k}{i}E_{n-1}(x^i)\\ &=E_{n-1}(x^k)+\frac{1}{m}\sum_{i=0}^{k-1}\binom{k}{i}E_{n-1}(x^i) \end{aligned}

想象一张无穷大的网格图:第 nn 列第 kk 行表示的是 En(xk)E_n(x^k)。对于每个点 (n,k)  (n>0,k0)(n,k)\ \ (n>0,k\geq 0),我们设立 kk 条边 (n1,i)(n,k)(n-1,i)\rightarrow(n,k)ii 取遍 0,1,,k10,1,\cdots,k-1),边权分别为 (ki)/m\binom{k}{i}/m,称经过它们为大跳;同时有边 (n1,k)(n,k)(n-1,k)\rightarrow(n,k),边权为 11。定义一条路径的权值为路径上所有边的边权之。又有 E0(xk)=[k=0]E_0(x^k)=[k=0],于是由上文转移式得到 En(xk)E_n(x^k) 等于在网格图上从 (0,0)(0,0)(n,k)(n,k) 的所有合法路径的权值之和。又因为非大跳的权值为 11,故我们只需考虑大跳的起终点。设某条路径有 cc 次大跳,每次大跳落点为 p0=0,p1,p2,,pc=kp_0=0,p_1,p_2,\cdots,p_c=k。那么,这条路径的权值为 i=1c1m(pipi1)=1mc(pcpcpc1)(pc1pc1pc2)(p2p2p1)(p1p1)=1mc(kp1p0,p2p1,,pcpc1)(pc=k)=k!i=1c1m(pipi1)!\begin{aligned} &\prod_{i=1}^c \frac 1m\binom{p_i}{p_{i-1}}\\ =&\frac{1}{m^c}\binom{p_c}{p_c-p_{c-1}}\binom{p_{c-1}}{p_{c-1}-p_{c-2}}\cdots\binom{p_2}{p_2-p_1}\binom{p_1}{p_1}\\ =&\frac{1}{m^c}\binom{k}{p_1-p_0,p_2-p_1,\cdots,p_c-p_{c-1}}&(p_c=k)\\ =&\frac{k!}{\prod_{i=1}^c\frac 1m(p_i-p_{i-1})!} \end{aligned}

于是我们不妨修改每条大跳边 (n1,kΔ)(n,k)  (Δ>0)(n-1,k-\Delta)\rightarrow(n,k)\ \ (\Delta>0) 的权值为 1mΔ!\frac{1}{m\Delta!}En(xk)E_n(x^k) 的实际值为路径权值和与 k!k! 的积。

24 pts\text{24 pts} – I – k105k\leq 10^5,生成函数与多项式快速幂

注意到从 (n1,k)(n-1,k) 转移到 (n,k+Δ)(n,k+\Delta) 的权只与 Δ\Delta 有关,自然想到生成函数的卷积。我们构造数列 fn\langle f_n\rangle,满足 f0=1,fi=1mi!  (i>0)f_0=1,f_i=\frac{1}{m\cdot i!}\ \ (i>0)。记 F(z)=1+1mz+12!mz2+F(z)=1+\frac{1}{m}z+\frac{1}{2!m}z^2+\cdots 为它的普通生成函数,则有 En(xk)=k![zk]Fn(z)E_n(x^k)=k!\cdot [z^k]F^n(z)

暴力求取快速幂,复杂度为 O(klog2k)\newcommand\bigO{\operatorname{O}}\bigO(k\log^2 k);使用多项式 exp,ln\exp,\ln 优化到 O(klogk)\bigO(k\log k)

24 pts\text{24 pts} – II – 多项式乘法

我们直接对所有路径的权值求和。枚举 cc,“枚举”所有合法落点序列(的差分形式),考虑大跳是在 nn 次转移的哪些位置进行的,得到如下式子: En(xk)=c=0min{n,k}(nc)1mcΔ1++Δc=k,i,0<ic,Δi>0(kΔ1,Δ2,,Δc)\begin{aligned} E_n(x^k)=&\sum_{c=0}^{\min\{n,k\}}\binom{n}{c}\frac{1}{m^c}\sum_{\substack{\Delta_1+\cdots+\Delta_c=k,\\ \forall i,0<i\leq c,\Delta_i>0}}\binom{k}{\Delta_1,\Delta_2,\cdots,\Delta_c} \end{aligned}

i,0<ic,Δi>0\forall i,0<i\leq c,\Delta_i>0 的限制很烦。若没有它,那么不难得到 Δ1++Δc=k(kΔ1,Δ2,,Δc)=(1+1++1c 个 1)k=ck \sum_{\Delta_1+\cdots+\Delta_c=k}\binom{k}{\Delta_1,\Delta_2,\cdots,\Delta_c}=(\underbrace{1+1+\cdots+1}_{c\text{ 个 }1})^k=c^k 考虑以该简化形式为基础,使用容斥原理计算带有 Δi>0\Delta_i>0 限制的结果。我们钦定其中 ii 个位置满足 Δj=0\Delta_j=0。于是剩下的 cic-iΔj\Delta_j 之和为 kk,是为 cic-i 项式系数,也即 Δ1++Δci=k(kΔ1,Δ2,,Δci,0,,0i 个 0)=(ci)k \sum_{\Delta_1+\cdots+\Delta_{c-i}=k}\binom{k}{\Delta_1,\Delta_2,\cdots,\Delta_{c-i},\underbrace{0,\cdots,0}_{i\text{ 个 }0}}=(c-i)^k 考虑从 cc 个位置中选取这 ii 个位置,乘上容斥系数,得到答案为 En(xk)=c=0min{n,k}(nc)1mci=0c(1)i(ci)(ci)k(1) \tag{1}E_n(x^k)=\sum_{c=0}^{\min\{n,k\}}\binom{n}{c}\frac{1}{m^c}\sum_{i=0}^{c}(-1)^i\binom{c}{i}(c-i)^k

内部的和式可以被改写为 c!i=0c((1)i/i!)((ci)k/(ci)!)c!\sum_{i=0}^c\left((-1)^i/i!\right)\left((c-i)^k/(c-i)!\right),可以用多项式乘法优化卷积。时间复杂度 O(klogk)\bigO(k\log k)

优化多项式乘法得到的另解

就算时间给够,我们似乎也不能简单地用 NTT(Z/nZ,n=998244353\mathbb{Z}/n\mathbb{Z},n=998244353 域上)计算 k222k\geq 2^{22} 时的卷积。原因很简单:这个群的阶只有 2232^{23} 的偶因数。但学习了宋佳兴学长的代码后发现,我们可以将数列作拆分:F(z)=F0(z)+z2lF1(z)+z2×2lF2(z)+F(z)=F_0(z)+z^{2^l}F_1(z)+z^{2\times 2^l}F_2(z)+\cdots 然后将每一部分分别相乘后再相加,就能得到正确的卷积结果。

常数优化
  • 手写不带分支的取模函数(用数的符号位判断是否应补全/减去 P=998244353P=998244353);
  • (NTT 过程中)不要每一次迭代时重新计算 O(nlogn)\bigO(n\log n) 次原根的次幂,可以预处理后花费 O(nlogn)\bigO(n\log n) 的空间存下来。

时间复杂度 O(kl+k/2l2k)\bigO(kl+\lceil k/2^l\rceil^2k)(点值相乘后直接相加,最后再 IDFT 以省时),尝试后发现 l=19l=19 时较快。

正解

直接从期望的定义下手:所有情况下 xkx^k 的和除以情况总数。枚举 xx,那么答案为 En(xk)=x=0nxk(nx)(m1)nxmn=(m1m)nx=0nxk(nx)1(m1)x E_n(x^k)=\frac{\sum_{x=0}^{n}x^k\binom{n}{x}(m-1)^{n-x}}{m^n}=\left(\frac{m-1}{m}\right)^n\sum_{x=0}^nx^k\binom{n}{x}\frac{1}{(m-1)^x}

暴力计算该式答案,将得到 5 pts\text{5 pts} 的好成绩(nkn\leq k)。我们希望得到 O(k)\bigO(k) 的算法,故尝试xkx^k第二类斯特林数转化为下降幂xk=c=0kxc{kc}=c=0kxc(1)cc!i=0c(1)i(ci)ik原式=(m1m)nx=0n(nx)1(m1)xc=0kxc(1)cc!i=0c(1)i(ci)ik=(m1m)nc=0k(1)cc!(i=0c(1)i(ci)ik)x=0n(nx)xc(m1)x\begin{aligned} x^k&=\sum_{c=0}^kx^{\underline c}\begin{Bmatrix}k\\c\end{Bmatrix}=\sum_{c=0}^kx^{\underline c}\frac{(-1)^c}{c!}\sum_{i=0}^c(-1)^i\binom ci i^k\\ \text{原式}&=\left(\frac{m-1}{m}\right)^n\sum_{x=0}^n\binom{n}{x}\frac{1}{(m-1)^x}\sum_{c=0}^kx^{\underline c}\frac{(-1)^c}{c!}\sum_{i=0}^c(-1)^i\binom ci i^k\\ &=\left(\frac{m-1}{m}\right)^n\sum_{c=0}^k\frac{(-1)^c}{c!}\left(\sum_{i=0}^c(-1)^i\binom ci i^k\right)\boxed{\sum_{x=0}^{n}\binom{n}{x}\frac{x^{\underline c}}{(m-1)^x}} \end{aligned} 化简方框内和式: x=0n(nx)xc(m1)x=x=0nn!x!(nx)!x!(xc)!1(m1)x=x=cn(ncxc)nc(m1)x=x=0nc(ncx)nc(m1)x+c=nc1(m1)c(mm1)nc=ncmnc(m1)n\begin{aligned} \sum_{x=0}^{n}\binom{n}{x}\frac{x^{\underline c}}{(m-1)^x}&=\sum_{x=0}^{n}\frac{n!}{x!(n-x)!}\frac{x!}{(x-c)!}\frac{1}{(m-1)^x}\\ &=\sum_{x=c}^n\binom{n-c}{x-c}\frac{n^{\underline c}}{(m-1)^x}\\ &=\sum_{x=0}^{n-c}\binom{n-c}x\frac{n^{\underline c}}{(m-1)^{x+c}}\\ &=n^{\underline c}\frac{1}{(m-1)^c}\left(\frac{m}{m-1}\right)^{n-c}=n^{\underline c}\frac{m^{n-c}}{(m-1)^n} \end{aligned} 原式=(m1m)nc=0k(1)cc!ncmnc(m1)ni=0c(1)i(ci)ik=c=0min{n,k}(nc)1(m)ci=0c(1)i(ci)ik\begin{aligned} \text{原式}&=\left(\frac{m-1}{m}\right)^n\sum_{c=0}^k\frac{(-1)^c}{c!}n^{\underline c}\frac{m^{n-c}}{(m-1)^n}\sum_{i=0}^c(-1)^i\binom ci i^k\\ &=\sum_{c=0}^{\min\{n,k\}}\binom{n}{c}\frac{1}{(-m)^c}\sum_{i=0}^c(-1)^i\binom ci i^k \end{aligned}

与部分分解法式 (1)(1) 殊途同归。现在考虑它的化简。记 lmt=min{n,k}\newcommand\lmt{\text{lmt}}\lmt=\min\{n,k\}(nc)(ci)\binom{n}{c}\binom{c}{i} 惹人注意,我们尝试交换求和顺序并交换指标: 原式=i=0lmt(1)iikc=ilmt(nc)(ci)1(m)c=i=0lmt(1)iik(ni)c=ilmt(nici)1(m)c=i=0lmt(1)iik1(m)ic=0lmti(nic)1(m)c\begin{aligned} \text{原式}&=\sum_{i=0}^{\lmt}(-1)^ii^k\sum_{c=i}^{\lmt}\binom nc\binom ci\frac{1}{(-m)^c}\\ &=\sum_{i=0}^{\lmt}(-1)^ii^k\binom ni\sum_{c=i}^{\lmt}\binom{n-i}{c-i}\frac{1}{(-m)^c}\\ &=\sum_{i=0}^{\lmt}(-1)^ii^k\frac{1}{(-m)^i}\sum_{c=0}^{\lmt-i}\binom{n-i}c\frac{1}{(-m)^c} \end{aligned}

h(i)=c=0lmti(nic)1(m)ch(i)=\sum_{c=0}^{\lmt-i}\binom{n-i}c\frac{1}{(-m)^c}。假若 lmt=n\lmt=n,也即 nkn\leq k,那么显然有 h(i)=(1+1m)ni=(mm1)nih(i)=\left(1+\frac{1}{-m}\right)^{n-i}=\left(\frac{m}{m-1}\right)^{n-i};否则似乎难以求出它的封闭形式。但我们发现在 ii 不同时,变化的只有二项式系数的上指标。根据递推公式 (nm)=(n1m)+(n1m1)  (n,m>0)\binom{n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1}\ \ (n,m>0) 以及 (n0)=1  (n0)\binom n0=1\ \ (n\geq 0),我们尝试从 h(i+1)h(i+1) 转移到 h(i)  (i<lmt)h(i)\ \ (i<\lmt)。转写为 h(i)=c=0lmti(nic)1(m)c=(ni0)1(m)0+c=1lmti((n(i+1)c)+(n(i+1)c1))1(m)c=(n(i+1)0)1(m)0+(c=1lmti(n(i+1)c)1(m)c)+1m(c=0lmt(i+1)(n(i+1)c)1(m)c)=(h(i+1)+(n(i+1)lmti)1(m)lmti)1mh(i+1)\begin{aligned} h(i)&=\sum_{c=0}^{\lmt-i}\binom{n-i}c\frac{1}{(-m)^c}\\ &=\binom{n-i}0\frac{1}{(-m)^0}+\sum_{c=1}^{\lmt-i}\left(\binom{n-(i+1)}c+\binom{n-(i+1)}{c-1}\right)\frac{1}{(-m)^c}\\ &=\binom{n-(i+1)}0\frac{1}{(-m)^0}+\left(\sum_{c=1}^{\lmt-i}\binom{n-(i+1)}c\frac{1}{(-m)^c}\right)+\frac{1}{-m}\left(\sum_{c=0}^{\lmt-(i+1)}\binom{n-(i+1)}c\frac{1}{(-m)^c}\right)\\ &=\left(h(i+1)+\binom{n-(i+1)}{\lmt-i}\frac{1}{(-m)^{\lmt-i}}\right)-\frac 1mh(i+1) \end{aligned} answer=i=0lmt(1)iik1(m)ih(i) \text{answer}=\sum_{i=0}^{\lmt}(-1)^ii^k\frac{1}{(-m)^i}h(i)

h(lmt)h(\lmt) 可以在 O(lmt)\bigO(\lmt) 的时间内算出;而所有上指标与 nn 相关的二项式系数,下指标均不超过 lmtk\lmt\leq k,可以通过下降幂等递推求出。于是我们可以 O(k)\bigO(k) 的时间计算出本题答案。

R99501601 记录详情

以下代码因省空间省时间而可读性较差,仅供参考。

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
#include <bits/stdc++.h> using namespace std; #define inl __always_inline typedef unsigned long long ull; using ulll = __uint128_t; constexpr uint N = 1e7 + 10, P = 998244353; uint n, m, k, p[N], pk[N], fac[N], *ppt = p; ulll ans; constexpr uint *const inv = p, *const f = fac; inl ull fpow (ull a, ull b) { ull c = 1; a %= P; for (; b; b >>= 1) { if (b & 1) (c *= a) %= P; (a *= a) %= P; } return c; } inl void calc_inv () { constexpr uint *const fact = inv; fact[0] = 1; for (ull x = 1; x < N; ++x) fact[x] = fact[x-1] * x % P; ull finv = fpow (fact[N-1], P-2); for (ull x = N-1; x; --x) inv[x] = finv * fact[x-1] % P, (finv *= x) %= P; } inl void sieve () { pk[1] = 1; for (ull x = 2, _pk, y; x < N; ++x) { if (!fac[x]) fac[x] = *ppt++ = x, pk[x] = fpow (x, k); _pk = pk[x]; for (uint *pt = p; pt != ppt && (y = *pt*x) <= N-1 && fac[x] >= *pt; ++pt) fac[y] = *pt, pk[y] = _pk * pk[*pt] % P; } } int main () { /* */ scanf ("%u%u%u", &n, &m, &k); const uint lmt = min (n, k), invm = fpow (m, P-2), minvm = invm * (P-1ull) % P; sieve (); calc_inv (); f[lmt+1] = 0; uint *pt1 = inv, *_f = f + lmt, *pt2 = pk; ull p = lmt, co = 1; while (~p) *_f = (_f[1] * (minvm + 1ull) + co) % P, --_f, co = co * (n-p--) % P * *++pt1 % P * minvm % P; pt1 = inv, _f = f, p = 0, co = 1; while (p <= lmt) ans += co * *pt2++ * (ulll) *_f++, (co *= *++pt1 * (n-p++) % P * invm % P) %= P; printf ("%llu", ull (ans % P)); return 0; }
  • 2023年1月31日