BZOJ1430 小猴打架 < Prufer序列+组合数学 >

Problem

小猴打架

Time  Limit:  5  Sec\mathrm{Time\;Limit:\;5\;Sec}
Memory  Limit:  162  MB\mathrm{Memory\;Limit:\;162\;MB}

Description

一开始森林里面有NN只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友。每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友。经过N1N-1次打架之后,整个森林的小猴都会成为好朋友。 现在的问题是,总共有多少种不同的打架过程。 比如当N=3N=3时,就有{12,13}\lbrace1-2,1-3\rbrace {12,23}\lbrace1-2,2-3\rbrace {13,12}\lbrace1-3,1-2\rbrace {13,23}\lbrace1-3,2-3\rbrace {23,12}\lbrace2-3,1-2\rbrace {23,13}\lbrace2-3,1-3\rbrace六种不同的打架过程。

Input

一个整数NNN106N\le10^6

Output

一行,方案数mod9999991\mod{9999991}

Sample Input

1
4

Sample Output

1
96

标签:Prufer序列 组合数学

Solution

Prufer序列\mathrm{Prufer}序列可知,一棵有nn个点的树与一个长为n2n-2的序列一一对应。那么确定出这样的序列的方案数即可确定最后形成的树的形态。易知这样的序列共有nn2n^{n-2}个。再考虑构建树的顺序,即为n1n-1个元素的全排列数,总数为(n1)!(n-1)!。故答案为 nn2(n1)!mod9999991n^{n-2}-(n-1)!\mod{9999991}

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
#define MOD 9999991
using namespace std;
typedef long long lnt;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n; lnt ans = 1;
int main() {
read(n);
for (int i = 1; i <= n-2; i++) (ans *= 1LL*n) %= MOD;
for (int i = 1; i <= n-1; i++) (ans *= 1LL*i) %= MOD;
return printf("%lld\n", ans), 0;
}