[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;
}
原文地址:https://www.cnblogs.com/hbyer/p/10026787.html