1. 程式人生 > >【概率與期望】AGC019 F Yes or No

【概率與期望】AGC019 F Yes or No

分析:

首先,很容易搞出來一個N^2的DP做法,顯然會T,但是對發現正解有很大幫助:
將這個DP轉換為一個網格,就變為:從起始點(n,m)出發,到達目標點(0,0)的期望路徑長度。

首先,有一個很厲害的結論:因為每次都是按照最優策略選答案,所以不妨設n>=m,那麼一定能答對n次。證明很顯然,每次當n>m時我們都會n的那一項,儘管答案可能會錯,但錯了之後,n會更大,我們更會選n。直到最終沒有m了,或者終於答對一次,n減少1。

有了這個結論以及其證明的過程,顯然不在對角線(i,i)上的點已經不用考慮了。其選擇方案之和永遠為n。

顯然,在對角線上的點,我們只能隨便選一個答案,無論選哪個都將離開對角線,並且期望得分都為1/2。

因此,我們可以爆枚每個對角線上的點被選中的概率,把它乘以1/2累加起來即可。

最後把累加的和加上n就做完了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 1000010
#define MOD 998244353
using namespace std;
typedef long long ll;
ll fac[MAXN],ifac[MAXN];
ll ans;
ll fsp(ll x,int y)
{ ll res=1; while(y){ if(y&1) res=res*x%MOD; x=x*x%MOD; y>>=1; } return res; } void prepare(){ fac[0]=1; for(int i=1;i<=1000000;i++) fac[i]=fac[i-1]*i%MOD; ifac[1000000]=fsp(fac[1000000],MOD-2); for(int i=1000000;i>=1;i--) ifac[i-1]=ifac[i]*i%MOD; } ll C(int n,int m){ return fac[n]*ifac[
m]%MOD*ifac[n-m]%MOD; } int main(){ int n,m; prepare(); SF("%d%d",&n,&m); if(n<m) swap(n,m); for(int i=1;i<=m;i++) ans=(ans+C(2*i,i)*C(n+m-2*i,n-i)%MOD)%MOD; ans=ans*fsp(2ll*C(n+m,n)%MOD,MOD-2)%MOD; ans=(ans+n)%MOD; PF("%lld",ans); }