题解:[AGC019F] Yes or No

设当前有 \(a\) 个 Yes 和 \(b\) 个 No(假设 \(a\ge b\),否则互换即可),则一定猜 Yes,且我们按照固定的顺序依次询问每道题(因为按照什么顺序都是一样的),则可以画成这样的网格:

每个点的坐标表示当前剩的 Yes 和 No,我们会从 \((a,b)\) 开始,到 \((0,0)\) 结束。其中加粗的线表示我们会做的选择,而正确的答案就对应一条折线,我们要求的就是这条折线上加粗的线的数量的期望。

考虑如果一条折线不越过直线 \(y=x\),其答案定然为 \(a\)。否则,每一次越过 \(y=x\),她一定会折回 \(y=x\),期间会增加 \(1\) 的贡献,所以在 \((i,i)\) 这处会有额外的 \(\frac{\binom{a+b-2i}{b-i}\binom{2i}{i}}{2\binom{a+b}{a}}\) 的贡献,其中 \(\binom{a+b-2i}{b-i}\binom{2i}{i}\) 是经过 \((i,i)\) 的折线数量,\(\frac 12\) 是有 \(\frac 12\) 的概率会往左走(也就是往左走的折线数量占总折线数量的一半),\(\frac 1{\binom{a+b}{a}}\) 是总折线数量。直接计算然后加上 \(a\) 就做完了,时间复杂度 \(O(a+b)\)

参考资料:题解 AT2705 【AGC019F Yes or No】

Code:

#include<iostream>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
typedef long long ll;
const int mod=998244353,maxn=1e6+5;
ll fac[maxn],inv[maxn];
inline ll qpow(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1)res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
inline void init(int n){
	fac[0]=1;
	rep(v1,1,n)fac[v1]=fac[v1-1]*v1%mod;
	inv[n]=qpow(fac[n],mod-2);
	per(v1,n,1)inv[v1-1]=inv[v1]*v1%mod;
}
inline ll c(int m,int n){
	if(n>m)return 0;
	return fac[m]*inv[m-n]%mod*inv[n]%mod;
}
int main(){
	int in,im;
	cin>>in>>im;
	if(in<im)swap(in,im);
	init(in+im);
	ll ans=0;
	rep(v1,1,im)ans=(ans+c(in+im-v1-v1,in-v1)*c(v1+v1,v1))%mod;
	ans=ans*qpow(c(in+im,in),mod-2)%mod*qpow(2,mod-2)%mod;
	cout<<(ans+in)%mod<<endl;
	cin>>in;
	return 0;
}
posted @ 2025-04-05 00:01  FugiPig  阅读(34)  评论(0)    收藏  举报