其他分享
首页 > 其他分享> > AGC019F Yes or No

AGC019F Yes or No

作者:互联网

题意

有 N+M 个问题,其中有 N 个问题的答案是 YES,M 个问题的答案是 NO

当回答一个问题之后,会知道这个问题的答案,求最优策略下期望对多少。

答案对 998244353 取模。

题解

首先可以想到 \(O(nm)\) 枚举分别剩下几个然后计算每一步的贡献

然后式子推不动,考虑一波实际意义

就是说第一象限有一张 \(n* m\) 的网格 (n>=m),然后从 (0,0) 出发有一条斜率为 1 的射线

从 (n,m) 走到 (0,0),若所在位置在射线左边会回答 NO,否则为 YES

而 \(m+n\choose n\) 种答案序列可以看成一些从 (n,m) 到 (0,0) 的折线

考虑每一条折线的贡献,发现在射线右边部分的贡献是向左走的步数,在射线左边的是向下走的步数,在射线上钦定为向左走的步数

然后可以将射线上的部分翻到射线下,答案是 n+刚好到射线上的点的概率* \(\frac{1}{2}\)

代码

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long 
const int N=1e6+11;
const int mod=998244353;
int n,m,k;
int inv[N];
int jc[N],ny[N];
il int read(){
	int s=0;char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
int C(int x,int y){
	if(y<0||x<y)return 0;
	if(x==y||y==0)return 1;
	return jc[x]*ny[y]%mod*ny[x-y]%mod;
}
int F(int x,int y){return C(n+m-x-y,n-x)*C(x+y,x)%mod*k%mod;}
int fm(int x,int y){
	int s=1;for(;y;y>>=1,x=x*x%mod){
		if(y&1)s=s*x%mod;
	}return s;
}
void pre(){
	inv[0]=inv[1]=1;
	ny[0]=jc[0]=1;
	for(int i=1;i<N;++i)jc[i]=jc[i-1]*i%mod;
	ny[N-1]=fm(jc[N-1],mod-2);
	for(int i=N-2;i;--i){
		ny[i]=ny[i+1]*(i+1)%mod;
		inv[i+1]=ny[i+1]*jc[i]%mod;
	}
}
signed main(){
	pre();n=read(),m=read();
	if(n<m)swap(n,m);int ans=0;
	k=fm(C(n+m,m),mod-2);
	for(int i=1;i<=m;++i){
		ans+=F(i,i)*inv[2]%mod;
	}cout<<(ans+n)%mod<<endl;
}

标签:AGC019F,ch,No,int,射线,答案,Yes,步数,mod
来源: https://www.cnblogs.com/sitiy/p/16025453.html