AtCoder Grand Contest 019F Yes or No

190 篇文章 2 订阅
13 篇文章 0 订阅

题面

题意

你要做一共 ( n + m ) (n+m) (n+m)道判断题,其中有m道题的答案是对,n道题的答案是错,当你做一道题之后,就可以知道对错,则你期望最多能做对多少题。

做法

首先最优方法肯定是写当前剩余数量最多的答案,我们可以将求正确期望改为求错误期望,对此建一张图:
在这里插入图片描述
横纵坐标分别表示此时剩下的答案数,自下而上的边表示此时答案是对的题较多但正确答案是错,自右向左的边则相反,这样将每条边的权值为设1,答案就可以转化为从右下角到左上角的路径的边权和的期望,为了求这个,可以先加一些边,再把新加的边的贡献减掉:
在这里插入图片描述
可以发现这张图一共添加了 min ⁡ ( m , n ) \min(m,n) 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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值