[CF1477F] Nezzar and Chocolate Bars

Problem

給定 \(n\) 個長度爲 \(a_i\) 的巧克力,每次以正比於 \(a_i\) 的概率取得一個巧克力,然後在 \((0,a_i)\) 中隨機選擇一個實數 \(r\) 並將其分成 \(r,a_i-r\) 兩個部分放回。

計算使得所有巧克力的長度均小於 \(K\) 的期望操作次數。

\(n\le 50,k,\sum a_i\le 2000\)

Sol

這裏將每塊巧克力看成線段,長度爲 \(L_i\),線段長度總和爲 \(L\)

n=1

首先,我們來考慮 \(n=1\) 的情形。

問題變成:給你一條長度爲 \(L\),每次等概率在線段上隨機一個點切斷,求期望次數,使得第一次所有線段長度 \(\le K\)

現在,假設切 \(n\) 次得到 \(n\) 個點 \(X_{(1)},X_{(2)},\cdots,X_{(n)}\),並且按照從小到大排序得到 \(X_1\le X_2\le\cdots X_n\)。令 \(X_0=0\),按題意,必須滿足

\[\begin{cases} X_i-X_{i-1}\le K,0<i\le n\\ L-X_n\le K \end{cases} \]

\(w=\frac KL\),設 \(z_1=X_1-X_0\)\(z_2=X_2-X_1\)\(\cdots\)\(z_n=X_n-X_1\),我們要求概率

\[p_n=f(z_1,z_2,\cdots,z_n)=n!\int_{0<z_1<w,1-w\le\sum z_i\le1}\mathrm dz_1\mathrm dz_2\cdots=n!w^n\int_{0<z_1<1,\frac1w-1\le\sum z_i\le\frac1w}\mathrm dz_1\mathrm dz_2\cdots \]

考慮求後面的積分,發現其可以差分,記

\[F(x)=\int_{0<z_1<1,\sum z_i\le x}\mathrm dz_1\mathrm dz_2\cdots \]

則之前的積分可以寫成

\[F(\frac1w)-F(\frac1w-1) \]

現在我們來求 \(F(x)\)。其實 \(\sum_{i=1}^nz_i\) 遵循 Irwin-Hall 分佈,其 累積分佈函數 滿足

\[F(x)=\frac1{n!}\sum_{k=0}^{\lfloor x\rfloor}(-1)^k{n\choose k}(x-k)^n \]

我們從 OI 的角度試圖不嚴謹地證明它。首先假設 \(0\le x\le1\),當 \(n=1\) 時,\(F(x)=x\);當 \(n=2\) 時,\(F(x)\) 是二維平面座標系中的直角三角形面積,爲 \(\frac{x^2}2\);當 \(n=3\) 時,是直角四面體體積,爲 \(\frac{x^3}6\cdots\) 不難發現,當 \(x\le 1\) 時,\(F(x)=\frac{x^n}{n!}\)。當 \(x\ge 1\) 時,我們可以通過容斥,每次枚舉哪些 \(z_i\ge 1\),不斷扣掉,直接推出來上式成立。

\(p_n\) 表示帶回原式

\[\begin{aligned} p_n&=n!w^n\left(\frac1{n!}\sum_{k=0}^{x}(-1)^k{n\choose k}(\frac1w-k)^n-\frac1{n!}\sum_{k=0}^{x-1}(-1)^k{n\choose k}(\frac1w-1-k)^n\right)\\ &=\sum_{k=0}^x(-1)^k{n\choose k}(1-kw)^n-\sum_{k=0}^{x-1}(-1)^k{n\choose k}(1-(k+1)w)^n\\ &=1+\sum_{k=1}^x(-1)^k{n\choose k}(1-kw)^n+\sum_{k=1}^x(-1)^k{n\choose k-1}(1-kw)^n\\ &=1+\sum_{k=1}^x(-1)^k{n+1\choose k}(1-kw)^n \end{aligned} \]

這裏 \(x=\lfloor\frac1w\rfloor\)

最終答案根據期望定義,有

\[E=\sum_{n\ge 0}1-p_n=\sum_{n\ge 0}\sum_{k=1}^x(-1)^{k-1}{n+1\choose k}(1-kw)^n \]

利用公式

\[\sum_{n\ge k}{n\choose k}x^n=x^k(1-x)^{-(k+1)} \]

即可求解。

n 任意

這裏定義第 \(i\) 條線段,切 \(m\) 次得到結果非法的概率爲 \(q_{i,m}\),由上面得到

\[q_{i,m}=\sum_{k=1}^{\lfloor\frac{L_i}K\rfloor}(-1)^{k-1}{m+1\choose k}(1-\frac K{L_i}k)^m \]

\(p_m\) 表示切 \(m\)不合法 的概率,則有

\[p_m=1-\sum_{j_1+j_2+\cdots+j_n=m}\frac{m!}{j_1!j_2!\cdots j_n!}\prod_{i=1}^n(1-q_{i,j_i})\left(\frac{L_i}L\right)^{j_i} \]

\(Q_i(x)\) 表示後面部分的 EGF,則

\[Q_i(x)=\sum_{m\ge 0}(1-q_{i,m})\left(\frac{L_i}L\right)^m\frac{x^m}{m!} \]

\(P(x)\) 表示 \(p_n\) 的 EGF,則

\[P(x)=\exp(x)-\prod_{i=1}^nQ_i(x) \]

現在詳細推導 \(Q_i(x)\)

\[\begin{aligned} Q_i(x)&=\sum_{m\ge 0}\frac1{m!}\left(1-\sum_{k=1}^{\lfloor\frac{L_i}K\rfloor}(-1)^{k-1}{m+1\choose k}(1-\frac K{L_i}k)^m\right)\left(\frac{L_i}Lx\right)^m\\ &=\exp\left(\frac{L_i}Lx\right)-\frac1{m!}\sum_{k=1}^{\lfloor\frac{L_i}K\rfloor}(-1)^{k-1}\sum_{m\ge k-1}{m+1\choose k}\left(\frac{L_i-kK}Lx\right)^m\\ &=\exp\left(\frac{L_i}Lx\right)-\sum_{k=1}^{\lfloor\frac{L_i}K\rfloor}(-1)^{k-1}\sum_{m\ge k-1}\frac{m+1}{k!(m+1-k)!}\left(\frac{L_i-kK}Lx\right)^m \end{aligned} \]

由於

\[\begin{aligned} \sum_{m\ge k-1}\frac{m+1}{k!(m+1-k)!}y^m=\sum_{m\ge k-1}\left(\frac{m+1-k}{k!(m+1-k)!}+\frac{k}{k!(m+1-k)!}\right)y^m\\ =\sum_{m\ge k}\frac{y^m}{k!(m-k)!}+\sum_{m\ge k-1}\frac{y^m}{(k-1)!(m+1-k)!}=(\frac{y^k}{k!}+\frac{y^{k-1}}{(k-1)!})\exp(y) \end{aligned} \]

所以有

\[Q_i(x)=\exp\left(\frac{L_i}Lx\right)-\sum_{k=1}^{\lfloor\frac{L_i}K\rfloor}(-1)^{k-1}\left(\frac1{k!}\left(\frac{L_i-kK}L\right)^kx^k+\frac1{(k-1)!}\left(\frac{L_i-kK}L\right)^{k-1}x^{k-1}\right)\exp\left(\frac{L_i-kK}Lx\right) \]

\[\Rightarrow Q_i(x)=\sum_{k=0}^{\lfloor\frac{L_i}K\rfloor}(-1)^k\left(\frac1{k!}\left(\frac{L_i-kK}L\right)^kx^k+[k\ne 0]\frac1{(k-1)!}\left(\frac{L_i-kK}L\right)^{k-1}x^{k-1}\right)\exp\left(\frac{L_i-kK}Lx\right) \]

求出來的 \(P(x)\) 是 EGF,而設 \(P^*(x)\)\(p_m\) 的 OGF。通過轉化,我們用 \(\sum_{t,r}a_{t,r}x^{t-r}\exp\left(\left(1-\dfrac KLt\right)x\right)\) 的形式表示 \(P(x)\),其中 \(0\le t\le L, 0\le r\le\min(n,t)\)。現在,我們想要 \(P(x)\rightarrow P^*(x)\),就要着手考慮 \(x^k\exp(Cx)\) 的形式,不難發現

\[x^k\exp(Cx)=\sum_{i\ge 0}\frac{C^i}{i!}x^{i+k}=\sum_{i\ge 0}\frac{(i+k)!C^i}{i!}\frac{x^{i+k}}{(i+k)!} \]

轉變成 OGF:

\[A(x)=\sum_{i\ge 0}\frac{(i+k)!C^i}{i!}x^{i+k}=\frac{k!}{C^k}\sum_{i\ge 0}{k+i\choose k}(Cx)^{i+k}=\frac{k!}{C^k}\sum_{i\ge k}{i\choose k}(Cx)^i=x^kk!(1-Cx)^{-(k+1)} \]

通過這樣我們就能得到 \(P^*(x)\)。最後答案爲 \(P^*(1)\),直接代值即可。

複雜度 \(\mathcal O(nL^2)\),使用 NTT 可使複雜度降成 \(\mathcal O(nL\log n\log nL)\)

#include <bits/stdc++.h>
#define pb push_back
using std::vector;
typedef vector<int> poly;
typedef vector<poly> poly2;
const int N = 55, M = 2005, P = 998244353;
int n, K, L, l[N], len;
int inc(int a, int b) { return (a += b) >= P ? a - P : a; }
int qpow(int a, int b) {
	int t = 1;
	for (; b; b >>= 1, a = 1LL * a * a % P)
		if (b & 1) t = 1LL * t * a % P;
	return t;
}
int W[M * 2], inv[M], fac[M], ifac[M];
void prework(int n) {
	for (int i = 1; i < n; i <<= 1)
		for (int j = W[i] = 1, Wn = qpow(3, (P - 1) / i >> 1); j < i; j++)
			W[i + j] = 1LL * W[i + j - 1] * Wn % P;
	inv[1] = fac[0] = ifac[0] = 1;
	for (int i = 2; i <= n; i++)
		inv[i] = 1LL * (P - P / i) * inv[P % i] % P;
	for (int i = 1; i <= n; i++)
		fac[i] = 1LL * fac[i - 1] * i % P, ifac[i] = 1LL * ifac[i - 1] * inv[i] % P;
}
void fft(poly &a, int n, int op) {
	a.resize(n);
	static int rev[M * 4] = {0};
	for (int i = 1; i < n; i++)
		if ((rev[i] = rev[i >> 1] >> 1 | (i & 1 ? n >> 1 : 0)) > i) std::swap(a[i], a[rev[i]]);
	for (int q = 1; q < n; q <<= 1)
		for (int p = 0; p < n; p += q << 1)
			for (int i = 0, t; i < q; i++)
				t = 1LL * W[q+i] * a[p+q+i] % P, a[p+q+i] = inc(a[p+i], P - t), a[p+i] = inc(a[p+i], t);
	if (op) return;
	for (int i = 0, inv = qpow(n, P - 2); i < n; i++) a[i] = 1LL * a[i] * inv % P;
	std::reverse(a.begin() + 1, a.end());
}
int getsz(int n) { int x = 1; while (x < n) x <<= 1; return x; }
struct Poly {
	poly2 a; int n, m;
	poly &operator [] (int i) { return a[i]; }
	Poly(poly2 &po, int nn, int mm) : a(po), n(nn), m(mm) {}
};
vector<Poly> F;
Poly operator * (Poly a, Poly b) {
	poly2 res;
	int n = a.n + b.n - 1, m = a.m + b.m - 1, ln = getsz(n), lm = getsz(m);
	for (int i = 0; i < a.n; i++) fft(a[i], lm, 1);
	for (int i = 0; i < b.n; i++) fft(b[i], lm, 1);
	res.resize(n);
	for (int i = 0; i < lm; i++) {
		poly l, r;
		for (int j = 0; j < a.n; j++) l.pb(a[j][i]);
		for (int j = 0; j < b.n; j++) r.pb(b[j][i]);
		fft(l, ln, 1), fft(r, ln, 1);
		for (int j = 0; j < ln; j++) l[j] = 1LL * l[j] * r[j] % P;
		fft(l, ln, 0);
		for (int j = 0; j < n; j++) res[j].pb(l[j]);
	}
	for (int i = 0; i < n; i++) fft(res[i], lm, 0), res[i].resize(m);
	return Poly(res, n, m);
}
int main() {
	scanf("%d%d", &n, &K);
	for (int i = 1; i <= n; i++)
		scanf("%d", &l[i]), L += l[i];
	len = L + 1; prework(len);
	for (int i = 1; i <= n; i++) {
		poly tmp0, tmp1; poly2 tmp;
		for (int j = 0; j <= l[i] / K; j++) {
			int t0, t1;
			if (l[i] == K * j) t0 = t1 = 0;
			else {
				t0 = 1LL * (j & 1 ? P - 1 : 1) * ifac[j] % P * qpow(1LL * (l[i] - j * K) * inv[L] % P, j) % P;
				if (j) t1 = 1LL * (j & 1 ? P - 1 : 1) * ifac[j - 1] % P * qpow(1LL * (l[i] - j * K) * inv[L] % P, j - 1) % P; else t1 = 0;
			}
			tmp0.pb(t0), tmp1.pb(t1);
		}
		F.pb(Poly(tmp = {tmp0, tmp1}, 2, l[i] / K + 1));
	}
	for (int i = 1; i < n; i <<= 1)
		for (int j = 0; j < n - i; j += i * 2)
			F[j] = F[j] * F[j + i];
	int ans = 0;
	for (int i = 0; i < F[0].n; i++)
		for (int j = 0; j < F[0].m; j++) {
			if (j < i || j == 0 || K * j == L) continue;
			ans = (ans + 1LL * fac[j - i] * qpow(L, j - i + 1) % P * qpow(qpow(1LL * j * K % P, P - 2), j - i + 1) % P * F[0][i][j]) % P;
		}
	printf("%d\n", ans ? P - ans : 0);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章