学习犹如逆水行舟,不进则退
小猴打架
题目描述
一开始森林里面有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。
Sample Input
4
Sample Output
96
Hint
50%的数据N<=103。
100%的数据N<=106。
题目思路
这题需要一个知识点就是Purfer数列
形象的栗子就是,以一个点为跟,剩下的n-1个集以何种方法与这个根相连。
一共是nn-2种情况。
然后既然确定了这个根了,那么剩下的n-1个有(n-1)!种排列方法
故,答案为(n-1)!*nn-2
通过普通的模拟运算就可以做出来了
AC代码如下
#include<algorithm>
#include<iostream>
#include<string.h>
#include<utility>
#include<stdio.h>
#include<vector>
#include <stack>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<map>
#pragma warning(disable:4244)
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
inline ll read() {
ll c = getchar(), Nig = 1, x = 0;
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')Nig = -1, c = getchar();
while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
return Nig * x;
}
inline void out(ll a)
{
if (a < 0)putchar('-'), a = -a;
if (a >= 10)out(a / 10);
putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
ll res = 1;
while (n > 0) {
if (n & 1)res = (res * x) % mod;
x = (x * x) % mod; n >>= 1;
}
return res;
}
#define read read()
ll ans = 0;
int main()
{
ll n = read;
ans = qpow(n, n - 2, 9999991);
for (int i = 1; i < n; i++)
{
ans *= i;
ans %= 9999991;
}
cout << ans << endl;
return 0;
}
书山有路勤为径,学海无涯苦作舟。