題面
題意
你要做一共道判斷題,其中有m道題的答案是對,n道題的答案是錯,當你做一道題之後,就可以知道對錯,則你期望最多能做對多少題。
做法
首先最優方法肯定是寫當前剩餘數量最多的答案,我們可以將求正確期望改爲求錯誤期望,對此建一張圖:
橫縱座標分別表示此時剩下的答案數,自下而上的邊表示此時答案是對的題較多但正確答案是錯,自右向左的邊則相反,這樣將每條邊的權值爲設1,答案就可以轉化爲從右下角到左上角的路徑的邊權和的期望,爲了求這個,可以先加一些邊,再把新加的邊的貢獻減掉:
可以發現這張圖一共添加了條邊,而且這張圖中任意一條從左下角到右上角的路徑的權值都是,很好計算,而新加的邊的貢獻就是經過這條邊的路徑數,也很好計算。
代碼
#include<bits/stdc++.h>
#define ll long long
#define N 1001000
#define MN 1000000
#define M 998244353
using namespace std;
ll n,m,ans,jc[N],nj[N];
inline ll C(ll u,ll v){return jc[u]*nj[v]%M*nj[u-v]%M;}
inline ll po(ll u,ll v)
{
ll res=1;
for(;v;)
{
if(v&1) res=res*u%M;
u=u*u%M;
v>>=1;
}
return res;
}
int main()
{
ll i,j;
jc[0]=1;for(i=1;i<=MN;i++) jc[i]=jc[i-1]*i%M;
nj[MN]=po(jc[MN],M-2);for(i=MN-1;i>=0;i--) nj[i]=nj[i+1]*(i+1)%M;
cin>>m>>n;
if(m>n) swap(m,n);
ans=C(m+n,m)*m%M;
for(i=1;i<=m;i++)
{
ans-=C(2*i-1,i)*C(m+n-2*i,n-i)%M;
ans%=M;
}
ans=(ans+M)%M;
cout<<(m+n-ans*po(C(m+n,m),M-2)%M+M)%M;
}