AGC019 F- Yes or No 题解

题目传送门

题目大意: n + m n+m n+m 道判断题,有 n n n 道的答案为正确,有 m m m 道的答案为错误,进行 n + m n+m n+m 轮提问,每次随机给你一道题,你不知道它的答案,但是你回答后他会告诉你是否答对了,问你在最优策略下期望能答对多少题。

题解

显然最优策略是每次答剩余题数较多的那类题,一顿找规律后不难发现一定能答对 max ⁡ ( n , m ) \max(n,m) max(n,m) 道题。

证明的话,不妨令 n > m n>m n>m,那么此时肯定回答正确,假如答案正确,那么 a n s + 1 , n − 1 ans+1,n-1 ans+1,n1,否则 a n s ans ans 不变, m − 1 m-1 m1,此时 n n n 是不变的,依然满足 n > m n>m n>m,也就是说,让 n n n 减小的唯一条件是答对了,即只有答对了能让较大的数减小,所以肯定能答对 max ⁡ ( n , m ) \max(n,m) max(n,m) 道。

但是还有一个需要计算的地方,如果操作过程中,出现了 n = m n=m n=m,那么此时无论答对还是答错,后继状态都是 n , n − 1 n,n-1 n,n1(可能是 n n n正确 + + + m m m错误,也可能反过来,但都是一样的),即这一步无论是否答对,后面依然能答对 n n n 个,也就是说,这一步如果答对了,那么会在 max ⁡ ( n , m ) \max(n,m) max(n,m) 的基础上额外多对 1 1 1 道。

于是对于每个 ( i , i ) (i,i) (i,i),统计出有多少条路径经过它,设为 d d d,那么他提供的额外期望值就是 d / 2 d/2 d/2

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 1000010
#define mod 998244353

int n,m;
int fac[maxn],inv[maxn],inv_fac[maxn];
void FacInit(int N){
	fac[0]=inv_fac[0]=inv[1]=1;
	for(int i=1;i<=N;i++)fac[i]=1ll*fac[i-1]*i%mod;
	for(int i=2;i<=N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<=N;i++)inv_fac[i]=1ll*inv_fac[i-1]*inv[i]%mod;
}
int Binom(int x,int y){return 1ll*fac[x]*inv_fac[y]%mod*inv_fac[x-y]%mod;}
void add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
int ksm(int x,int y){int re=1;for(;(y&1?re=1ll*re*x%mod:0),y;y>>=1,x=1ll*x*x%mod);return re;}

int main()
{
	scanf("%d %d",&n,&m);FacInit(n+m);
	if(n<m)swap(n,m);int ans=0;
	for(int i=1;i<=m;i++)add(ans,1ll*Binom(n-i+m-i,n-i)*Binom(i+i,i)%mod);
	ans=1ll*ans*ksm(2ll*Binom(n+m,n)%mod,mod-2)%mod;add(ans,n);
	printf("%d",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值