AtCoder Grand Contest 019F Yes or No

題面

題意

你要做一共(n+m)(n+m)道判斷題,其中有m道題的答案是對,n道題的答案是錯,當你做一道題之後,就可以知道對錯,則你期望最多能做對多少題。

做法

首先最優方法肯定是寫當前剩餘數量最多的答案,我們可以將求正確期望改爲求錯誤期望,對此建一張圖:
在這裏插入圖片描述
橫縱座標分別表示此時剩下的答案數,自下而上的邊表示此時答案是對的題較多但正確答案是錯,自右向左的邊則相反,這樣將每條邊的權值爲設1,答案就可以轉化爲從右下角到左上角的路徑的邊權和的期望,爲了求這個,可以先加一些邊,再把新加的邊的貢獻減掉:
在這裏插入圖片描述
可以發現這張圖一共添加了min(m,n)\min(m,n)條邊,而且這張圖中任意一條從左下角到右上角的路徑的權值都是min(m,n)\min(m,n),很好計算,而新加的邊的貢獻就是經過這條邊的路徑數,也很好計算。

代碼

#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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章