题解 | #小䓤的质因数#

小䓤的质因数

https://ac.nowcoder.com/acm/problem/222910

D

简单的概率期望题。

考虑把问题抽象成有 nn 个牌堆,第 ii 个牌堆有 cic_i 张牌,每次随机两个牌堆转移一张牌 iji\rightarrow j,其中 i,ji,j 任选。

然后分别计算出无穷次操作之后哪个牌堆会拥有最后的 ci\sum c_i 张牌的概率,再乘上它的贡献就好了。

考虑如何计算这个概率,首先扔一个结论:

  • 当只有两堆牌的时候,一堆是 aa,一堆是 bb,其中 aa 留下来的概率是 aa+b\dfrac{a}{a+b}

简单证明一下这个结论,设 f(x)f(x) 表示剩 xx 张牌时,这堆能活着留下来不死的概率:

  • f(0)=0f(0)=0:剩 00 张牌游戏结束,死得彻底。
  • f(a+b)=1f(a+b)=1:剩 a+ba+b 张,就是把对方“掏空”了,100%100\% 存活。
  • f(x)=f(x1)+f(x+1)2f(x)=\dfrac{f(x-1)+f(x+1)}{2}:关键的式子,其实也好懂,剩 xx 张牌时无非两种转移的方向,要么自己少一张(被别人拿走),要么自己多一张(拿走别人的),两种情况出现的概率相同,加起来求平均就是答案。

然后把最后一个式子稍微变换一下,得到:

f(x+1)f(x)=f(x)f(x1)f(x+1)-f(x)=f(x)-f(x-1)

这啥玩意?一看就知道是等差数列的形式!(连续三项 a,b,ca,b,c 满足 cb=bac-b=b-a!)

所以对于等差数列而言,f(x)=xa+bf(x)=\dfrac{x}{a+b} 不就显然了么!

知道了上面这些东西之后,第 jj 个质因子的贡献显然就是:

ci\sum c_i 表示所有 cic_i 的和)

(cjci)(pjci)\left(\dfrac{c_j}{\sum c_i}\right) * \left(p_j ^ {\sum c_i}\right)

左边是概率,右边是贡献,乘一块就是它的期望啦!

最后给每个数的贡献的期望求个和,这道题就做完了 \sim

#include<cstdio>
#define int long long
int init(){
	char c = getchar();
	int x = 0, f = 1;
	for (; c < '0' || c > '9'; c = getchar())
		if (c == '-') f = -1;
	for (; c >= '0' && c <= '9'; c = getchar())
		x = (x << 1) + (x << 3) + (c ^ 48);
	return x * f;
}
void print(int x){
	if (x < 0) x = -x, putchar('-');
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int N = (int) 1e6 + 5, Mod = 998244353;
int p[N], c[N];
int quick_mod(int a, int b){
	int s = 1; a %= Mod;
	while (b) {
		if (b & 1) s = s * a % Mod;
		a = a * a % Mod; b >>= 1;
	}
	return s;
}
void Relax(int&a, int b){
	a = a + b >= Mod ? a + b - Mod : a + b;
}
signed main(){
	int n = init(), sum = 0;
	for (int i = 1; i <= n; ++i)
		p[i] = init(), sum += (c[i] = init());
	int ans = 0, inv = quick_mod(sum, Mod - 2);
	for (int j = 1; j <= n; ++j)
		Relax(ans, c[j] * inv % Mod * quick_mod(p[j], sum) % Mod);
	print(ans), putchar('\n');
}
全部评论

相关推荐

评论
3
1
分享
牛客网
牛客企业服务