[2020-09-11 CQBZ/HSZX多校联测 T2] 泰拳警告(组合数+数学期望)

description

题目描述
小七擅长泰拳,某天他打算与小枣切磋拳技,一共需要进行 n 次比赛。
由于双方拳技难分上下,每场比赛小七获胜或落败的概率都是 1/p+2 ,平局的概率是 p/p+2
若最后小七获胜场数大于落败场次,且平局次数为 k ,则能获得 k + 1 奖励分
小七想知道,他能获得的奖励分的期望是多少呢?为了避免精度误差,你需要输出答案在模 998244353 意义下的结果

输入格式
输入文件 fight.in 包含一行,输入两个正整数依次表示 n; p
输出格式
输出文件 fight.out 包含一行,仅一个非负整数,表示答案在模 998244353 意义下的结果

样例输入
2 1
样例输出
221832079

样例解释
两局都胜,或胜一局平一局是合法的,期望得分为 1/3 × 1/3 ×1+2× 1/3 × 1/3 ×2 = 5/9,在模 998244353 意义下为 221832079

数据范围及约定

测试点编号n特殊性质
1 ∼ 4≤ 2000
5 ∼ 8≤ 105
9 ∼ 12≤ 3 × 106p = 1
13 ∼ 20≤ 3 × 106

对于 100% 的数据,满足 1 ≤ n ≤ 3 × 106; 1 ≤ p < 998244351 。可以证明答案一定能表示成一个既约分数 u/v,你需要找到满足 v × w ≡ 1 mod 998244353的自然数 w ,输出 u × w mod 998244353

solution

case 0 : 上来直接搞大 D P DP DP d p i , j : dp_{i,j}: dpi,j: 赢了 i i i场,输了 j j j场的概率,自然就平了 n − i − j n-i-j nij

枚举每一场是赢了还是输了甚至于平了,这是 O ( n 3 ) O(n^3) O(n3)的,连最基础的测试点都不能拿到

case 1~4 :猜测改写 d p i , j : dp_{i,j}: dpi,j: 在第 i i i轮为止平了 j j j的概率,将胜场和负场合并在一起

d p i , j ∗ 1 p + 2 ∗ 2 → d p i + 1 , j dp_{i,j}*\frac{1}{p+2}*2\rightarrow dp_{i+1,j} dpi,jp+212dpi+1,j

d p i , j ∗ p p + 2 → d p i + 1 , j + 1 dp_{i,j}*\frac{p}{p+2}\rightarrow dp_{i+1,j+1} dpi,jp+2pdpi+1,j+1

最后平了 k k k场的方案数,如果胜了 i i i,负了 j j j;则一定对应有一种胜了 j j j,负了 i i i,看似 / 2 /2 /2就行了,总是恰好有一种胜场大于负场

但是如果i=j,就都不能取,单独减掉

case 5~8 : n ≤ 1 0 5 n\le 10^5 n105,没有特殊性质,应该是拿来给选手被卡log的安慰

case 9~12 : p = 1 p=1 p=1,意味着胜负平都是一样的概率,应该可以利用数学方法计算

case 13~20 :最后就是正解了,私以为还是p=1的数据提供了可以数学计算的灵感

枚举平了 k k k场,因为胜负的概率一样,所以平了 k k k场的每种情况概率都是一样的

( p p + 2 ) k ⋅ ( 1 p + 2 ) n − k (\frac{p}{p+2})^k·(\frac{1}{p+2})^{n-k} (p+2p)k(p+21)nk

每种可能其实相当于在 n n n个位置中,选 k k k个为止为平,选 i i i个位置为胜,剩下自然就是负

C ( n , k ) ∗ C ( n − k , i ) C(n,k)*C(n-k,i) C(n,k)C(nk,i)

这里一旦枚举 i i i就又变成 n 2 n^2 n2

考虑 i i i的限制,胜场大于负场,即 i > n − k − i ⇒ i ∈ ( n − k 2 , n − k ] i>n-k-i\Rightarrow i\in(\frac{n-k}{2},n-k] i>nkii(2nk,nk]

随着 k k k的枚举,计算的 i i i范围也要变化, C ( n − k , i ) C(n-k,i) C(nk,i)似乎不能通过求和然后乘以一个分数转移到下一个 k k k,也就省不掉

考试时,在这里我陷入了僵局

思索许久无果后,我想起了与组合系数紧密相连的杨辉三角

i i i的范围对应在上面是一段后缀区间,斜着的不对齐,不能直观冲击我的数学左脑

于是乎,我果断选择枚举负场次数i

这样在杨辉三角里面就是一段左对齐的区间选址

/0123456
01 2 0 2^0 20
111 2 1 2^1 21
2121 2 2 2^2 22
31331 2 3 2^3 23
414641 2 4 2^4 24
515101051 2 5 2^5 25
61615201561 2 6 2^6 26

杨辉三角有太多的性质了

  • i i i行的和为 2 i 2^i 2i
  • 每一行是对称的

这两个性质便是去掉一个 n n n复杂度的关键

因为负场是不到一半的

e.g. 胜负场 6 6 6,负场可能为 0 / 1 / 2 0/1/2 0/1/2,在杨辉三角中就是减去 1 + 6 + 15 1+6+15 1+6+15

这等于先减去中间的 C ( i , i 2 ) C(i,\frac{i}{2}) C(i,2i),再除以二

e.g.胜负场 5 5 5,负场可能为 0 / 1 / 2 0/1/2 0/1/2,直接减去Z总和的一半

所以说负场 i i i的贡献可以根据 n − k n-k nk的奇偶直接算

这中间设计逆元,幂等,需要预处理后 O ( 1 ) O(1) O(1)调用

卡的就是懒人非要在计算时反复算快速幂的 log ⁡ \log log

code

#include <cstdio>
#define mod 998244353
#define int long long
#define maxn 3000005
int n, p;
int fac[maxn], inv[maxn], mi_2[maxn], Inv[maxn];

int qkpow( int x, int y ) {
	int ans = 1;
	while( y ) {
		if( y & 1 ) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

void init() {
	fac[0] = inv[0] = 1;
	for( int i = 1;i <= n;i ++ )
		fac[i] = fac[i - 1] * i % mod;
	inv[n] = qkpow( fac[n], mod - 2 );
	for( int i = n - 1;i;i -- )
		inv[i] = inv[i + 1] * ( i + 1 ) % mod;
	mi_2[0] = Inv[0] = 1; int mi = 1;
	for( int i = 1;i <= n;i ++ ) {
		mi_2[i] = mi_2[i - 1] * 2 % mod;
		mi = mi * ( p + 2 ) % mod;
	}
	Inv[n] = qkpow( mi, mod - 2 );
	for( int i = n - 1;i;i -- )
		Inv[i] = Inv[i + 1] * ( p + 2 ) % mod;
}

int C( int n, int m ) {
	return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

signed main() {
	freopen( "fight.in", "r", stdin );
	freopen( "fight.out", "w", stdout );
	scanf( "%lld %lld", &n, &p );
	init();
	int ans = 0, Inv2 = qkpow( 2, mod - 2 ), mi_p = 1;
	for( int i = 0;i < n;i ++ ) { //平i场 
		int t = mi_p * Inv[i] % mod * Inv[n - i] % mod * C( n, i ) % mod;
		int k; //枚举负场 
		if( ( n - i ) & 1 ) //胜场+负场=奇数 n-i
			k = mi_2[n - i - 1];
		else
			k = ( mi_2[n - i] - C( n - i, ( n - i ) >> 1 ) + mod ) % mod * Inv2 % mod;
		ans = ( ans + k * t % mod * ( i + 1 ) ) % mod;
		mi_p = mi_p * p % mod;
	}
	printf( "%lld\n", ans );
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值