AGC056E Cheese【概率期望,dp】

给定长为 \(n\) 的圆周,定义沿顺时针方向距离为 \(x\) 的位置的坐标为 \(x\)。初始时坐标 \(i+0.5\) 的位置上有一只老鼠。

进行 \(n-1\) 次操作,每次操作以 \(a_i\%\) 的概率选择 \(i\pod{0\le i<n}\),在坐标 \(i\) 放上一块奶酪,之后奶酪顺时针移动,每次遇到没吃过奶酪的老鼠,都有 \(1/2\) 的概率被吃掉。

\(\forall k\in[0,n)\),求最后没吃奶酪的老鼠是坐标位于 \(k+0.5\) 的老鼠的概率 \(\bmod 998244353\)

\(n\le 40\)\(a_i\ge 0\)\(\sum a_i=100\)


只考虑 \(k=n-1\) 的情况,分别做即可。

本题最关键的结论是,在确定了每个坐标 \(i\) 被放奶酪的次数 \(c_i\) 之后,概率仅与奶酪经过 \(-0.1\) 的次数 \(x\) 有关,而与放奶酪的顺序无关。

\(b_i\) 表示奶酪经过 \(i+0.1\) 的次数,则 \(b_i=x-i+\sum_{j=0}^ic_j\),而整个过程实际上是一个奶酪与老鼠的匹配,所以与放奶酪的顺序无关,乘上个可重排列方案数即可,而老鼠决策的概率为 \(2^{-x}\prod_{i=0}^{n-2}(1-2^{-b_i})\),表示第 \(0,1,\cdots,n-2\) 个老鼠至少要吃掉一个奶酪(虽然实际上只有第一次是吃了的),而第 \(n-1\) 个老鼠不能吃奶酪。

而如果任意取 \(c_i\)\(x\)\(b_i\) 有可能是负的,但因为 \(b_{i+1}-b_i\ge -1\) 所以此时必有一个 \(b_i=0\),算出的概率即为 \(0\),因此不需考虑这种情况。

最后答案即为 \((n-1)!\sum2^{-x}\prod_{i=0}^{n-2}(1-2^{i-\sum_{j\le i}c_j}\cdot 2^{-x})\prod_{i=0}^{n-1}\frac{a_i^{c_i}}{c_i!}\),要对所有 \(x\ge 0\) 求和所以应该表示为 \(2^{-x}\) 的多项式,对 \(p\) 次项系数乘上 \(1/(1-2^{-p})\) 然后加起来即可。直接 dp 维护,单次计算时间复杂度 \(O(n^4)\)

然而你会发现你输出的恰好是答案的 \(2\) 倍,因为对于任意一个合法方案,把它加上一个独立的圈之后的概率也被算了进去,而加一个圈之后概率变为原来的 \(1/2\)(不能被第 \(n-1\) 个老鼠吃掉),所以算出来的是答案的 \(1+1/2+1/4+\cdots=2\) 倍,最后除以 \(2\) 即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 42, mod = 998244353, iv100 = 828542813;
int ksm(int a, int b){
    if(b < 0) b += mod - 1;
    int res = 1;
    for(;b;b >>= 1, a = (LL)a * a % mod)
        if(b & 1) res = (LL)res * a % mod;
    return res;
}
void qmo(int &x){x += x >> 31 & mod;}
int n, pr[N], a[N], fac[N], inv[N], f[N][N], g[N][N], val[N];
void solve(){
    memset(f, 0, sizeof f); **f = *val = 1;
    for(int i = 0;i < n;++ i){
        for(int j = 1;j < n;++ j) val[j] = (LL)val[j-1] * inv[j] % mod * a[i] % mod;
        memset(g, 0, sizeof g);
        for(int j = 0;j < n;++ j)
            for(int k = 0;j + k < n;++ k)
                for(int l = 0;l <= i;++ l)
                    g[j+k][l] = (g[j+k][l] + (LL)f[j][l] * val[k]) % mod;
        memset(f, 0, sizeof f);
        for(int j = 0;j < n;++ j){
            int coe = ksm(2, i - j);
            if(i == n-1) for(int k = 0;k < n;++ k) f[j][k+1] = (LL)coe * g[j][k] % mod;
            else for(int k = 0;k <= i;++ k){qmo(f[j][k] += g[j][k] - mod); f[j][k+1] = mod - (LL)coe * g[j][k] % mod;}
        }
    }
    int res = 0;
    for(int i = 1, pw = 1;i <= n;++ i){
        res = (res + (LL)pw * f[n-1][i] % mod * ksm(2*pw-1, mod-2)) % mod;
        qmo(pw += pw - mod);
    }
    printf("%lld ", (LL)res * fac[n-1] % mod);
}
int main(){
    ios::sync_with_stdio(false);
    cin >> n; *fac = fac[1] = inv[1] = 1;
    for(int i = 2;i <= n;++ i){
        fac[i] = (LL)fac[i-1] * i % mod;
        inv[i] = mod - (LL)mod / i * inv[mod % i] % mod;
    }
    for(int i = 0;i < n;++ i){cin >> pr[i]; pr[i] = (LL)pr[i] * iv100 % mod;}
    for(int i = 0;i < n;++ i){
        for(int j = 0;j <= i;++ j) a[n+j-i-1] = pr[j];
        for(int j = i+1;j < n;++ j) a[j-i-1] = pr[j];
        solve();
    }
}
原文地址:https://www.cnblogs.com/AThousandMoons/p/15725267.html