Solution -「AGC 019F」「AT 2705」Yes or No
阿新 • • 發佈:2020-08-05
\(\mathcal{Description}\)
Link.
有 \(n+m\) 個問題,其中 \(n\) 個答案為 yes,\(m\) 個答案為 no。每次你需要回答一個問題,然後得知這個問題的正確答案。求最優策略下期望答對的題數。
\(n,m\le5\times10^5\)。
\(\mathcal{Solution}\)
顯然貪心策略:當 \(n\not=m\),猜較多的答案。
設 \(n>m\),無腦猜 yes,就一定能答對 \(n\) 道題。那麼所有 \(n\not=m\) 的情形下,猜對的期望次數之和就是 \(n\)。接下來只需要考慮 \(n=m\) 時的貢獻。
其實 OEIS 能找到 www。首先,\(n=m\) 時,猜中的概率顯然為 \(\frac{1}2\)。那麼貢獻次數呢?考慮成一張為網格圖,從 \((0,0)\) 向下或向右走,走到 \((n,m)\),求進過 \((i,i)\) 的概率。這就是經典的組合數問題嘛。綜上,答案為:
\[\max\{n,m\}+\frac{1}{2\binom{n+m}{n}}\sum_{i=1}^{\min\{n,m\}}\binom{2i}{i}\binom{n+m-2i}{n-i} \]
求出來就好啦,複雜度 \(\mathcal O(n+m)\)。
\(\mathcal{Code}\)
#include <cstdio> const int MAXN = 5e5, MOD = 998244353; int n, m, fac[MAXN * 2 + 5], ifac[MAXN * 2 + 5]; inline int qkpow ( int a, int b, const int p = MOD ) { int ret = 1; for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p; return ret; } inline void init ( const int n ) { fac[0] = 1; for ( int i = 1; i <= n; ++ i ) fac[i] = 1ll * i * fac[i - 1] % MOD; ifac[n] = qkpow ( fac[n], MOD - 2 ); for ( int i = n - 1; ~ i; -- i ) ifac[i] = ( i + 1ll ) * ifac[i + 1] % MOD; } inline int C ( const int n, const int m ) { return n < m ? 0 : 1ll * fac[n] * ifac[m] % MOD * ifac[n - m] % MOD; } int main () { scanf ( "%d %d", &n, &m ); if ( n < m ) n ^= m ^= n ^= m; init ( n + m ); int ans = n, inv = ( MOD + 1ll ) / 2 * qkpow ( C ( n + m, n ), MOD - 2 ) % MOD; for ( int i = 1; i <= m; ++ i ) { ans = ( ans + 1ll * inv * C ( 2 * i, i ) % MOD * C ( n + m - 2 * i, n - i ) ) % MOD; } printf ( "%d\n", ans ); return 0; }