1. 程式人生 > >agc019f - Yes or No

agc019f - Yes or No

urn one gpo stat return ret unique clas pass

F - Yes or No

Time limit : 2sec / Memory limit : 256MB

Score : 2000 points

Problem Statement

You are participating in a quiz with N+M questions and Yes/No answers.

It‘s known in advance that there are N questions with answer Yes and M questions with answer No, but the questions are given to you in random order.

You have no idea about correct answers to any of the questions. You answer questions one by one, and for each question you answer, you get to know the correct answer immediately after answering.

Suppose you follow a strategy maximizing the expected number of correct answers you give.

Let this expected number be P

?Q, an irreducible fraction. Let M=998244353. It can be proven that a unique integer R between 0 and M?1 exists such that P=Q×R modulo M, and it is equal to P×Q?1 modulo M, where Q?1 is the modular inverse of Q. Find R.

Constraints

  • 1≤N,M≤500,000
  • Both N and M are integers.

Partial Score

  • 1500 points will be awarded for passing the testset satisfying N
    =M and 1≤N,M≤105.

Solution

對於(a,b),我們肯定是猜數量大的那一個(若a>b,猜yes),相等就隨便猜一個
本以為是期望DP,很容易想到O(mn)的方法,統計每一條邊會被經過次的次數,每條邊的貢獻=max{x,y}/(x+y)*次數,然後除以總方案數即可。

但想到max{x,y}是經過y=x這一條線的時候發生改變,若從(n,m)->(0,0)不經y=x顯然有max(n,m)的貢獻。
考慮正常情況:將經過y=x的點的出邊從路徑中刪去,得到若幹段不經過y=x的路徑,有上面可知路徑的總貢獻為max(n,m)。

正解就只用單獨統計(i,i)點上出邊的貢獻,最後加上max(n,m)。

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=e[i].next)
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
typedef double DB;
using namespace std;
template <typename T> inline T read(T &a) {
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();a=f*x;
}
const int maxn=500000+10,mo=998244353;
int fac[maxn*2],inv[maxn*2];
int i,j,k,l,t,n,m,ans;
int ksm(int x,int y) {
    int ret=1;
    for(;y;x=(LL)x*x%mo,y>>=1) if(y&1) ret=(LL)ret*x%mo;
    return ret;
} 
int C(int n,int m) {
    if(n<m||m<0) return 0;
    return (LL)fac[n]*inv[m]%mo*inv[n-m]%mo;
}
int main() {
    read(n),read(m);
    if(n<m) swap(n,m);
    fac[0]=1;
    fo(i,1,n*2) fac[i]=(LL)fac[i-1]*i%mo;
    inv[n*2]=ksm(fac[n*2],mo-2);
    fd(i,n*2-1,0) inv[i]=(LL)inv[i+1]*(i+1)%mo;
    fo(i,1,m) (ans+=(LL)C(2*i,i)*C(n+m-2*i,n-i)%mo)%=mo;
    ans=(LL)ans*ksm(2*C(n+m,n)%mo,mo-2)%mo;
    ans=((n+ans)%mo+mo)%mo;
    printf("%d\n",ans);
}

agc019f - Yes or No