[bzoj1430] 小猴打架
题目描述
一开始森林里面有N只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友。每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友。经过N-1次打架之后,整个森林的小猴都会成为好朋友。 现在的问题是,总共有多少种不同的打架过程。 比如当N=3时,就有{1-2,1-3}{1-2,2-3}{1-3,1-2}{1-3,2-3}{2-3,1-2}{2-3,1-3}六种不同的打架过程。
输入输出格式
输入格式:
一个整数N。
输出格式:
一行,方案数mod 9999991。
输入输出样例
输入样例#1:
4
输出样例#1:
96
说明
50%的数据N<=10^3。 100%的数据N<=10^6。
这是luogu题面,bzoj题面(权限题)
题解
就是让你求\(n\)个点的有标号无根树的个数,个数为\(n^{n-2}\),证明大概就是\(prufer\)序列和无根树一一对应,然后这个个数就是\(prufer\)序列的个数,具体看这里。
然后由于加边是有顺序的,答案需要乘上一个(n-1)!,因为有\(n-1\)条边。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using std :: vector;
using std :: map;
using std :: clock;
#define ull unsigned long long
#define max(a,b) (a<b?b:a)
#define min(a,b) (a<b?a:b)
#define swap(x,y) x^=y^=x^=y
#define isdigit(ch) (ch>='0'&&ch<='9')
#define abs(x) (x<0?-x:x)
#define pb push_back
inline void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
}
inline void print(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);putchar(x%10+'0');
}
inline void write(int x) {print(x);puts("");}
const int mod = 9999991;
int main() {
int n;read(n);int ans=1;
for(int i=1;i<=n-2;i++) ans=1ll*ans*n%mod*i%mod;
ans=1ll*ans*(n-1)%mod;write(ans);
return 0;
}