# Algorithm Design

Cayley公式是说，一个完全图$K_n$$n^{n-2}$棵生成树，换句话说n个节点的带标号的无根树有$n^{n-2}$个。今天我学到了Cayley公式的一个非常简单的证明，证明依赖于Prüfer编码，它是对带标号无根树的一种编码方式。

# Code

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define ll long long
const int maxn = 3000;
const ll mod = 1000000000000000;
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int n, m, tot, cnt;
ll d[maxn], num[maxn], prime[maxn], check[maxn], ans[maxn], l = 1;
void getprime() {
for (int i = 2; i <= 1000; i++) {
if (!check[i])
prime[cnt++] = i;
for (int j = 0; j < cnt; j++) {
if (i * prime[j] > 1000)
break;
check[i * prime[j]] = 1;
if (i % prime[j] == 0)
break;
}
}
}
void solve(int a, int f) {
for (int k = 1; k <= a; k++) {
int x = k;
for (int i = 0; i < cnt; i++) {
if (x <= 1)
break;
while (x % prime[i] == 0) {
num[i] += f;
x /= prime[i];
}
}
}
}
void mul(int x) {
for (int i = 1; i <= l; i++)
ans[i] *= x;
for (int i = 1; i <= l; i++) {
ans[i + 1] += ans[i] / mod;
ans[i] %= mod;
}
while (ans[l + 1]) {
l++;
ans[l + 1] += ans[l] / mod;
ans[l] %= mod;
}
}
void print() {
for (int i = l; i; i--)
if (i == l)
printf("%lld", ans[i]);
else
printf("%06lld", ans[i]);
}
int main() {
getprime();
ans[1] = 1;
if (n == 1) {
if (!x || x == -1)
printf("1");
else
printf("0");
return 0;
}
for (int i = 1; i <= n; i++) {
if (!d[i]) {
printf("0");
return 0;
}
if (d[i] == -1)
m++;
else {
d[i]--;
tot += d[i];
}
}
if (tot > n - 2) {
printf("0");
return 0;
}
solve(n - 2, 1);
solve(n - 2 - tot, -1);
for (int i = 1; i <= n; i++)
solve(d[i], -1);
for (int i = 0; i < cnt; i++)
while (num[i]--)
mul(prime[i]);
for (int i = 1; i <= n - 2 - tot; i++)
mul(m);
print();
return 0;
}

posted on 2017-03-22 15:26 蒟蒻konjac 阅读(...) 评论(...) 编辑 收藏

• 随笔 - 172
• 文章 - 0
• 评论 - 30