LOJ3160 「NOI2019」斗主地
正解
想了半天发现自己连第一步都没有想出来……翻翻题解发现人们都不屑于讲这步……
就是说,洗牌之后,每种可能出现的方案的出现概率是相同的。
为什么……
从初始状态开始,一个最终状态的概率是若干步的概率乘起来的。看分母,是 n ! n! n!;看分子,是 A i ! ( n − A i ) ! A_i!(n-A_i)! Ai!(n−Ai)!,从而得证,概率为 1 ( n A i ) \frac{1}{\binom{n}{A_i}} (Ain)1。
当然有个组合意义的说法:因为两堆牌的内部的顺序固定,所以它们之间不存在区别。那么相当于有 n n n个球, A i A_i Ai个黑球 n − A i n-A_i n−Ai个白球,每次随机取出一个。最终形成的排列和原来的模型是一一对应的。
接下来是个结论: E i ( x ) E_i(x) Ei(x)表示 i i i次操作之后 x x x位置上值的期望,它可以表示成一个关于 x x x的二次多项式的形式。
知道这个结论之后,从 E i − 1 ( x ) E_{i-1}(x) Ei−1(x)推到 E i ( x ) E_i(x) Ei(x),只需要随便取三个值带入 E i ( x ) E_i(x) Ei(x)算,算完之后插值就可以得到它的多项式系数了。
做法讲完了,接下来是证明:
考虑归纳:
枚举位置 x x x上的球转移到位置 y y y的概率,于是有: ( n A i ) E i ( y ) = ∑ x = 1 A i ( y − 1 x − 1 ) ( n − y A i − x ) E i − 1 ( x ) + ∑ x = 1 n − A i ( y − 1 x − 1 ) ( n − y n − A i − x ) E i − 1 ( A i + x ) \binom{n}{A_i} E_i(y)=\sum_{x=1}^{A_i}\binom{y-1}{x-1}\binom{n-y}{A_i-x}E_{i-1}(x)+\sum_{x=1}^{n-A_i}\binom{y-1}{x-1}\binom{n-y}{n-A_i-x}E_{i-1}(A_i+x) (Ain)Ei(y)=∑x=1Ai(x−1y−1)(Ai−xn−y)Ei−1(x)+∑x=1n−Ai(x−1y−1)(n−Ai−xn−y)Ei−1(Ai+x)
我们要证这条式子是个只和 y y y有关的多项式。下面只考虑求左边,另一边同理:
由于 E i − 1 ( x ) E_{i-1}(x) Ei−1(x)为多项式,所以可以把它拆开成若干项分别算。直接普通的多项式可能不太好算,于是这里取 E i − 1 ( x ) = ∑ k = 0 2 f k ( x − 1 ) k ‾ E_{i-1}(x)=\sum_{k=0}^2f_k(x-1)^{\underline k} Ei−1(x)=∑k=02fk(x−1)k
于是要证: ∑ x = 1 A i ( y − 1 x − 1 ) ( n − y A i − x ) ( x − 1 ) k ‾ \sum_{x=1}^{A_i}\binom{y-1}{x-1}\binom{n-y}{A_i-x}(x-1)^{\underline k} ∑x=1Ai(x−1y−1)(Ai−xn−y)(x−1)k是个和 y y y有关的多项式。
原 式 = ( y − 1 k ) k ! ∑ x = 1 A i ( y − 1 − k x − 1 − k ) ( n − y A i − x ) = ( y − 1 k ) k ! ( n − k − 1 A i − k − 1 ) 原式=\binom{y-1}{k}k!\sum_{x=1}^{A_i}\binom{y-1-k}{x-1-k}\binom{n-y}{A_i-x}=\binom{y-1}{k}k!\binom{n-k-1}{A_i-k-1} 原式=(ky−1)k!x=1∑Ai(x−1−ky−1−k)(Ai−xn−y)=(ky−1)k!(Ai−k−1n−k−1)
(此处省略若干步骤,想推的同学慢慢推……)
看到这条式子和 x x x无关,并且显然有关 y y y的二次多项式。由此得证。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 10000010
#define M 500010
#define ll long long
#define mo 998244353
ll qpow(ll x, ll y = mo - 2) {
ll r = 1;
for (; y; y >>= 1, x = x * x % mo)
if (y & 1)
r = r * x % mo;
return r;
}
int n, m, type;
int fac[N], ifac[N];
void initC(int n) {
fac[0] = 1;
for (int i = 1; i <= n; ++i) fac[i] = (ll)fac[i - 1] * i % mo;
ifac[n] = qpow(fac[n]);
for (int i = n - 1; i >= 0; --i) ifac[i] = (ll)ifac[i + 1] * (i + 1) % mo;
}
ll C(int m, int n) { return (ll)fac[m] * ifac[n] % mo * ifac[m - n] % mo; }
ll f0, f1, f2;
ll dot(ll x) { return ((f2 * x + f1) % mo * x + f0) % mo; }
void cha_1n2(ll y1, ll yn, ll y2) {
static ll z1 = qpow(n - 1), zn = qpow((ll)(n - 1) * (n - 2) % mo), z2 = mo - qpow(n - 2);
y1 = y1 * z1 % mo;
yn = yn * zn % mo;
y2 = y2 * z2 % mo;
f0 = (y1 * n * 2 + yn * 2 + y2 * n) % mo;
f1 = (mo - (y1 * (n + 2) + yn * 3 + y2 * (n + 1)) % mo) % mo;
f2 = (y1 + yn + y2) % mo;
}
int main() {
// freopen("in.txt","r",stdin);
freopen("landlords.in", "r", stdin);
freopen("landlords.out", "w", stdout);
scanf("%d%d%d", &n, &m, &type);
initC(n);
f0 = 0, f1 = (type == 1), f2 = (type == 2);
for (int i = 1; i <= m; ++i) {
int A;
ll E1, En, E2;
scanf("%d", &A);
E1 = ((1 <= A ? C(n - 1, A - 1) * dot(1) : 0) + (1 <= n - A ? C(n - 1, n - A - 1) * dot(1 + A) : 0)) %
mo;
En = ((1 <= A ? C(n - 1, A - 1) * dot(A) : 0) + (1 <= n - A ? C(n - 1, n - A - 1) * dot(n) : 0)) % mo;
E2 = ((1 <= A ? C(n - 2, A - 1) * dot(1) : 0) + (1 <= n - A ? C(n - 2, n - A - 1) * dot(1 + A) : 0) +
(2 <= A ? C(n - 2, A - 2) * dot(2) : 0) + (2 <= n - A ? C(n - 2, n - A - 2) * dot(2 + A) : 0)) %
mo;
ll invC = (ll)ifac[n] * fac[n - A] % mo * fac[A] % mo;
cha_1n2(E1 * invC % mo, En * invC % mo, E2 * invC % mo);
}
int Q;
scanf("%d", &Q);
while (Q--) {
int x;
scanf("%d", &x);
printf("%lld\n", dot(x));
}
return 0;
}