TonyYin's Blog

Back

题意#

对于每个点 ii 随机与 [1,n][1, n] 中的一点连无向边,若连向自己,则保留该边并再次连边,一直重复至连到别的点上为止,求边数与连通块个数期望。

题解#

期望边数
#

首先,注意到每个点的期望次数一定相同,所以只算一个点即可。

之后利用几何分布相关定理,成功选到非自身的点的概率为 p=n1n\operatorname{p}=\frac{n-1}{n},期望 E=1p=nn1\operatorname{E}=\frac{1}{p}=\frac{n}{n-1}.

下面给出证明。

由期望的定义可知,设 p=n1np=\frac{n-1}{n},期望的计算式为:

E=1×(1p)0p+2×(1p)1p+3×(1p)2p++k×(1p)k1pE=1\times (1-p)^0\cdot p+2\times(1-p)^1\cdot p+3\times(1-p)^2\cdot p+\cdots+k\times (1-p)^{k-1}\cdot p

q=1pq=1-p,则:

E=p(1q0+2q1+3q2++kqk1)E=p\cdot (1\cdot q^0+2\cdot q^1+3\cdot q^2+\cdots + k\cdot q^{k-1})

S=EpS=\frac{E}{p},错位相减求和:

S=1q0+2q1+3q2++kqk1qS=0q0+1q1+2q2++(k1)qk1+kqk(1q)S=q0+q1+q2+q3++qk1kqk(1q)S=1qk1qkqk\begin{array}{rl} S&=1\cdot q^0+2\cdot q^1+3\cdot q^2+\cdots + k\cdot q^{k-1}\\ q\cdot S&=\textcolor{white}{0\cdot q^0}+1\cdot q^1+2\cdot q^2+\cdots+(k-1)\cdot q^{k-1}+k\cdot q^k\\ (1-q)S &= q^0+q^1+q^2+q^3+\cdots +q^{k-1}-k\cdot q^k\\ (1-q)S &= \dfrac{1-q^k}{1-q}-k\cdot q^k \end{array}

k+k\rightarrow +\infty 时,qk0q^k\rightarrow 0,所以:

S=1(1q)2S=\frac{1}{(1-q)^2}

期望为:

E=pS=p(1q)2=1pE=p\cdot S=\frac{p}{(1-q)^2}=\frac{1}{p}

nn 个点,所以题目所求答案为:

Ans=nE=nn1n=n2n1\operatorname{Ans}=n\cdot E=\frac{n}{\frac{n-1}{n}}=\frac{n^2}{n-1}

期望连通块数#

如果把每个点向其他点连的边看为有向边,则每个点的出度均为 11,所以每个连通块都是基环树。

因此:环的个数 == 基环树个数 == 连通块个数,下面求环的期望数量 EE.

E=所有图中环的总数图的总数=ABE=\frac{\text{所有图中环的总数}}{\text{图的总数}}=\frac{A}{B}

每个点都可以向外连边,图的总数为:

B=(n1)nB=(n-1)^n

环的总数:先枚举环的点数 ii,再确定哪些点在环上,其余点可以随便连边,环上的点再圆排列。

A=i=2n(ni)(n1)ni(i1)!A=\sum_{i=2}^n \binom{n}{i}\cdot (n-1)^{n-i}\cdot (i-1)!

化简:

E=AB=i=2n(ni)(n1)ni(i1)!(n1)n=i=2nn!(i1)!i!(ni)!(n1)i=i=2nn(n1)(n2)(ni+1)i(n1)i\begin{aligned} E &= \frac{A}{B}\\ &= \sum_{i=2}^n \dfrac{\binom{n}{i}\cdot (n-1)^{n-i}\cdot (i-1)!}{(n-1)^n}\\ &= \sum_{i=2}^n \dfrac{n!\cdot (i-1)!}{i!\cdot (n-i)!\cdot (n-1)^i}\\ &= \sum_{i=2}^n \dfrac{n\cdot (n-1)\cdot (n-2)\cdots(n-i+1)}{i\cdot (n-1)^i} \end{aligned}

不用预处理逆元,可以 O(n)\mathcal O(n) 计算。

代码#

#define int long long
using namespace std;
const int mod = 998244353;
int n, ans = 0;
inline int power(int x, int k) {
	int ret = 1;
	while(k) {
		if(k & 1) ret = ret * x % mod;
		x = x * x % mod;
		k >>= 1;
	}
	return ret;
}
inline int inv(int x) { return power(x, mod - 2); }
signed main() {
	cin >> n;
	printf("%lld\n", n * n % mod * inv(n - 1) % mod);
	int tmp = n, Pow = n - 1;
	for(int i = 2; i <= n; i++) {
		tmp = tmp * (n - i + 1) % mod;
		Pow = Pow * (n - 1) % mod;
		ans = (ans + tmp * inv(i) % mod * inv(Pow) % mod) % mod;
	}
	printf("%lld\n", ans);
	return 0;
}
cpp
【洛谷-P7474】「C.E.L.U-02」学术精神
https://www.tonyyin.top/blog/oi-solution/p7474
Author TonyYin
Published at August 2, 2022
Comment seems to stuck. Try to refresh?✨