CF1172C2 Nauuo and Pictures

CF1172C2


前情提要:聪明猫跟金勾爷 lzy duel,输掉了……

大概想到能分开每个位置考虑,以及 \(\texttt{01}\) 分开,然后意识到不得不回宿舍了,没继续想了。


首先注意到对于整个序列 dp 实在是太奢侈了,根本没法设计状态,只能对每个位置考虑。

先想到一个暴力 dp。设 \(f^k_{x, s_0, s_1}\) 表示对于某一位考虑,自己、喜欢的、不喜欢的操作次数分别为 \(x,\ s_0,\ s_1\) 时,继续操作,当前位被操作次数的期望。

这个大概是 \(O(nm^3)\) 的,于是可以过掉 easy version。


还是有点浪费,这种多个对象之间关系的 dp 大多可以拆成许多独立的部分,这个也一样。

我们注意到实际上“在对应的部分操作 \(k\) 次,某个位置被操作次数的期望”、“全局操作 \(k\) 次,两部分之一被操作次数的期望”,这两部分是完全分开的,因为操作在单个对象内的体现是一致的,要么 \(+1\) 要么 \(-1\)

先考虑“全局操作 \(k\) 次,两部分之一被操作次数的期望”。这个可以直接暴力 dp。设 \(f^k_{x}\) 表示一共操作 \(k\) 次,已经对喜欢的部分操作了 \(x\) 次,对喜欢的部分的操作的次数期望。复杂度 \(O(m^2)\)

还有“在对应的部分操作 \(k\) 次,某个位置被操作次数的期望”。我 duel 的时候没想清楚这个。

lzy:我们大胆猜测,对一个部分操作 \(k\) 次,某个位置 \(x\) 和这个部分其他的位置 \(y\),它们被操作次数的期望是和权值成比例的。

具体怎么证 lzy 也没说,只说这挺好证的……


大概说说吧。归纳一下应该很好搞。

假如操作是 \(+1\),设:

\[f^k_{x, y} \]

表示两个数的权值为 \(x\)\(y\) 的时候,再操作 \(k\) 次之后 \(x\) 的期望。

\[f^0_{x, y} = x \]

\[f^k_{x, y} = \dfrac{1}{x + y}\left(xf^{k - 1}_{x + 1, y} + yf^{k - 1}_{x, y + 1}\right) \]

要证:

\[f^k_{x, y} = \dfrac{x}{x + y}\cdot k + x \]

\(k = 0\) 显然满足。

\[f^k_{x, y} = \dfrac{1}{x + y}\left(x\left(\dfrac{x + 1}{x + y + 1} \cdot (k - 1) + x + 1\right) + y\left(\dfrac{x}{x + y + 1} \cdot (k - 1) + x\right) \right) \]

\[f^k_{x, y} = \dfrac{1}{x + y}\left(x\left(\dfrac{x}{x + y + 1} \cdot (k - 1) + x\right) + y\left(\dfrac{x}{x + y + 1} \cdot (k - 1) + x\right) + \dfrac{x\cdot(k - 1)}{x + y + 1} + x \right) \]

\[f^k_{x, y} = \dfrac{x\cdot (k - 1)}{x + y + 1} + x +\dfrac{1}{x + y}\left( \dfrac{x\cdot(k - 1)}{x + y + 1} + x \right) \]

\[f^k_{x, y} = \dfrac{x + y + 1}{x + y}\cdot\dfrac{x\cdot (k - 1)}{x + y + 1} + x +\dfrac{1}{x + y}\cdot x \]

\[f^k_{x, y} = \dfrac{x\cdot k}{x + y} + x \]

感觉挺脱裤子放屁的,总之就是这样。

code:

//        No mind to think.
//
//        No will to break.
//
//        No voice to cry suffering.
//
//        Born of God and Void.
//
//        You shall seal the blinding light that plagues their dreams.
//
//        You are the Vessel.
//
//        You are the Hollow Knight.
#ifdef N2
#define _GLIBCXX_DEBUG
#define LOG(...) fprintf(stderr, __VA_ARGS__)
#define DO(...) __VA_ARGS__
#else 
#define LOG(...) void(0)
#define DO(...) void(0)
#define NDEBUG
#endif
#define syncoff ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#include<bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int maxn = 2e5 + 10;
const int maxm = 3010;
using ll = long long;
ll Pow(ll a, ll b = mod - 2, ll mod = mod) {
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % mod;
        a = a * a % mod, b >>= 1;
    }
    return res;
}
int d;
int w[maxn];
int lk[maxn];
int s[2];
int n, m;
int f[maxm][maxm];
int F(int k, int d1) {
    if(~f[k][d1]) return f[k][d1];
    if(k == m) return f[k][d1] = d1;
    int d0 = k - d1;
    int w0 = (s[0] - d0 + mod) % mod;
    int w1 = (s[1] + d1) % mod;
    return f[k][d1] = ((ll)w0 * F(k + 1, d1) % mod + (ll)w1 * F(k + 1, d1 + 1) % mod) % mod * Pow((w0 + w1) % mod) % mod;
}
int main() {
    syncoff;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> lk[i];
    for(int i = 1; i <= n; i++) cin >> w[i];
    for(int i = 1; i <= n; i++) {
        s[lk[i]] += w[i];
        if(s[lk[i]] >= mod) s[lk[i]] -= mod;
    } 
    memset(f, -1, sizeof(f));
    int d1 = F(0, 0);
    int d0 = (m - d1 + mod) % mod;
    LOG("%d %d\n", d1, d0);
    for(int i = 1; i <= n; i++) {
        if(lk[i]) {
            cout << (w[i] + (ll)d1 * w[i] % mod * Pow(s[1]) % mod) % mod << '\n';
        } else {
            cout << (w[i] - (ll)d0 * w[i] % mod * Pow(s[0]) % mod + mod) % mod << '\n';
        }
    }
}
posted @ 2023-11-09 21:10  N2MENT  阅读(22)  评论(0)    收藏  举报