今天看了Prufer数列这个东西。
每一个Prufer数列和无根树是一一对应的。所以求出有多少符合要求的Prufer数列即可。
点i在Prufer数列中的出现次数为i的度数 - 1。
代码如下:【用分解质因数的方法,避免了高精除】
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int N = 10000 + 5, Prime_N = 1450 + 5; int n, Prime[Prime_N], A[N], p[Prime_N], Ans[N], P = 0, Bg, l, K; bool isPrime[N]; void Add(int num, int Flag) { for (int i = 1; i <= P; i++) { if (Prime[i] > num) break; while (num % Prime[i] == 0) { p[i] += Flag; num /= Prime[i]; } } } void Cheng(int num) { for (int i = 1; i <= l; i++) Ans[i] *= num; for (int i = 1; i <= l; i++) { Ans[i + 1] += Ans[i] / 10; Ans[i] %= 10; } while (Ans[l + 1]) { l++; Ans[l + 1] += Ans[l] / 10; Ans[l] %= 10; } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", A + i); for (int i = 1; i <= n; i++) isPrime[i] = true; isPrime[1] = false; for (int i = 2; i <= n; i++) { if (isPrime[i]) Prime[++P] = i; for (int j = 1; j <= P && i * Prime[j] <= n; j++) isPrime[i * Prime[j]] = false; } memset(p, 0, sizeof(p)); Bg = n - 2; K = n; for (int i = 1; i <= n; i++) { if (A[i] != -1) { K--; for (int j = 1; j <= A[i] - 1; j++) { Add(Bg, 1); Bg--; Add(j, -1); } } } Ans[1] = 1; l = 1; for (int i = 1; i <= P; i++) for (int j = 1; j <= p[i]; j++) Cheng(Prime[i]); for (int i = 1; i <= Bg; i++) Cheng(K); for (int i = l; i >= 1; i--) printf("%d", Ans[i]); printf("\n"); return 0; }
【BZOJ 1005】无根树的Prufer数列
时间: 2024-10-11 14:59:03