题目
[CodeForces 156D] Clues
分析
记联通块个数为
k
k
k ,枚举每个联通块的度数
d
i
d_i
d i (
∑
i
=
1
k
d
i
=
2
(
k
−
1
)
\sum_{i = 1}^{k} d_i = 2(k - 1)
∑ i = 1 k d i = 2 ( k − 1 ) ,每条边的贡献为
2
2
2 ,因此度数和为
2
(
k
−
1
)
2(k - 1)
2 ( k − 1 ) ),用重排列计算方案数,并且对于一个联通块,取里面一个点的方案数为联通块的大小
s
i
s_i
s i ,可得答案为
∑
∑
i
=
1
k
d
i
=
2
(
k
−
1
)
,
d
i
≥
1
(
(
∑
i
=
1
k
(
d
i
−
1
)
)
!
∏
i
=
1
k
(
(
d
i
−
1
)
!
)
∏
i
=
1
k
s
i
d
i
)
=
∑
∑
i
=
1
k
d
i
=
2
(
k
−
1
)
,
d
i
≥
1
(
(
k
−
2
)
!
∏
i
=
1
k
(
(
d
i
−
1
)
!
)
∏
i
=
1
k
s
i
d
i
)
\begin{aligned} & \sum_{\sum_{i = 1}^{k} d_i = 2(k - 1),\ d_i \geq 1} \left( \frac{\left( \sum_{i = 1}^{k}(d_i - 1) \right) !}{\prod_{i = 1}^{k} ((d_i - 1)!)} \prod_{i = 1}^{k} {s_i}^{d_i} \right) \\ =& \sum_{\sum_{i = 1}^{k} d_i = 2(k - 1),\ d_i \geq 1} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} ((d_i - 1)!)} \prod_{i = 1}^{k} {s_i}^{d_i} \right) \end{aligned}
= ∑ i = 1 k d i = 2 ( k − 1 ) , d i ≥ 1 ∑ ⎝ ⎛ ∏ i = 1 k ( ( d i − 1 ) ! ) ( ∑ i = 1 k ( d i − 1 ) ) ! i = 1 ∏ k s i d i ⎠ ⎞ ∑ i = 1 k d i = 2 ( k − 1 ) , d i ≥ 1 ∑ ( ∏ i = 1 k ( ( d i − 1 ) ! ) ( k − 2 ) ! i = 1 ∏ k s i d i ) 令
p
i
=
d
i
−
1
p_i = d_i - 1
p i = d i − 1 ,则原式变为
∑
∑
i
=
1
k
p
i
=
k
−
2
,
p
i
≥
0
(
(
k
−
2
)
!
∏
i
=
1
k
(
p
i
!
)
∏
i
=
1
k
s
i
p
i
+
1
)
\sum_{\sum_{i = 1}^{k} p_i = k - 2,\ p_i \geq 0} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} (p_i!)} \prod_{i = 1}^{k} {s_i}^{p_i + 1} \right)
∑ i = 1 k p i = k − 2 , p i ≥ 0 ∑ ( ∏ i = 1 k ( p i ! ) ( k − 2 ) ! i = 1 ∏ k s i p i + 1 ) 又由多项式定理
(
∑
i
=
1
k
s
i
)
k
−
2
=
∑
∑
i
=
1
k
p
i
=
k
−
2
,
p
i
≥
0
(
(
k
−
2
)
!
∏
i
=
1
k
(
p
i
!
)
∏
i
=
1
k
s
i
p
i
)
\left( \sum_{i = 1}^{k} s_i \right)^{k - 2} = \sum_{\sum_{i = 1}^{k} p_i = k - 2, p_i \geq 0} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} (p_i!)} \prod_{i = 1}^{k} {s_i}^{p_i} \right)
( i = 1 ∑ k s i ) k − 2 = ∑ i = 1 k p i = k − 2 , p i ≥ 0 ∑ ( ∏ i = 1 k ( p i ! ) ( k − 2 ) ! i = 1 ∏ k s i p i ) 因此,原式即为
(
∑
i
=
1
k
s
i
)
k
−
2
∏
i
=
1
k
s
i
=
n
k
−
2
∏
i
=
1
k
s
i
\left( \sum_{i = 1}^{k} s_i \right)^{k - 2} \prod_{i = 1}^{k} s_i = n^{k - 2} \prod_{i = 1}^{k} s_i
( i = 1 ∑ k s i ) k − 2 i = 1 ∏ k s i = n k − 2 i = 1 ∏ k s i 注意特判
k
=
1
k = 1
k = 1 的情况,并且要输出 1 % MOD
。
错因
并查集都能写错;
没有特判
k
=
1
k = 1
k = 1 的情况;
加上特判的时候只 puts("1")
,而不是 printf("%d", 1 % MOD)
;
并查集的 size
可以直接合并。
代码
#include <bits/stdc++.h>
const int MAXN = 100000 ;
int N, MOD, M, K;
int Fa[ MAXN + 5 ] , Size[ MAXN + 5 ] ;
int Find ( int x) {
return ( Fa[ x] == x) ? x : ( Fa[ x] = Find ( Fa[ x] ) ) ;
}
int Pow ( int x, int y) {
int ret = 1 ;
while ( y) {
if ( y & 1 )
ret = ( long long ) ret * x % MOD;
x = ( long long ) x * x % MOD;
y >>= 1 ;
}
return ret;
}
int main ( ) {
scanf ( "%d%d%d" , & N, & M, & MOD) ;
for ( int i = 1 ; i <= N; i++ )
Fa[ i] = i, Size[ i] = 1 ;
for ( int i = 1 ; i <= M; i++ ) {
int u, v; scanf ( "%d%d" , & u, & v) ;
int x = Find ( u) , y = Find ( v) ;
if ( x != y)
Fa[ x] = y, Size[ y] + = Size[ x] ;
}
int Ans = 1 ;
for ( int i = 1 ; i <= N; i++ ) {
Find ( Fa[ i] ) ;
if ( Fa[ i] == i)
K++ , Ans = ( long long ) Ans * Size[ i] % MOD;
}
if ( K == 1 )
return printf ( "%d" , 1 % MOD) , 0 ;
Ans = ( long long ) Ans * Pow ( N, K - 2 ) % MOD;
printf ( "%d" , Ans) ;
return 0 ;
}