【BZOJ 1005】【HNOI 2008】明明的烦恼

http://www.lydsy.com/JudgeOnline/problem.php?id=1005
答案是$$\frac{(n-2)!}{(n-2-sum)!×\prod_{i=1}{cnt}(d[i]-1)!}×(n-cnt)$$

\[sum=\sum_{i=1}^{cnt}(d[i]-1) \]

用到了prufer编码,参考http://www.cnblogs.com/zhj5chengfeng/p/3278557.html
注意要写高精度!

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
const int N = 1003;

bool notp[N];
int cnt = 0, n, d[N], num = 0, prime[N], sum = 0, tot[N];

void shai() {
	for (int i = 2; i <= n; ++i) {
		if (!notp[i]) prime[++num] = i;
		for (int j = 1; j <= num && i * prime[j] <= n; ++j) {
			notp[i * prime[j]] = true;
			if (i % prime[j] == 0)
				break;
		}
	}
}

void add(int x, int flag) {
	for (int i = 1; i <= num && x != 1; ++i)
		if (x % prime[i] == 0)
			while (x % prime[i] == 0) {
				tot[i] += flag;	
				x /= prime[i];
			}
}

ll ipow(int x, int b) {
	ll w = x, r = 1;
	while (b) {
		if (b & 1) r *= w;
		w = w * w;
		b >>= 1;
	}
	return r;
}

struct Big {
	int a[10003], len;
	Big() {memset(a, 0, sizeof(a)); len = 0;}
	Big operator * (const int &b) const {
		Big C;
		for (int i = 1; i <= len; ++i) {
			C.a[i] += a[i] * b;
			C.a[i + 1] += C.a[i] / 10;
			C.a[i] %= 10;
		}
		C.len = len;
		while (C.a[C.len + 1] != 0) {
			++C.len;
			C.a[C.len + 1] = C.a[C.len] / 10;
			C.a[C.len] %= 10;
		}
		return C;
	}
};

int main() {
	scanf("%d", &n);
	int dd;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &dd);
		if (dd != -1)
			d[++cnt] = dd, sum += dd - 1;
	}
	shai();
	
	if (n == 1) {
		puts(dd > 0 ? "0" : "1");
		return 0;
	}
	
	if (sum > n - 2) {
		puts("0");
		return 0;
	}
	
	int down = n - 2 - sum;
	for (int i = n - 2; i > down; --i) add(i, 1);
	for (int i = 1; i <= cnt; ++i)
		for (int j = d[i] - 1; j > 1; --j)
			add(j, -1);
	add(n - cnt, down);
	
	Big ans; ans.len = 1; ans.a[1] = 1;
	for (int i = 1; i <= num; ++i)
		for (int j = tot[i]; j >= 1; --j)
			ans = ans * prime[i];
	for (int i = ans.len; i >= 1; --i)
		putchar('0' + ans.a[i]);
	puts("");
	return 0;
}
posted @ 2016-12-18 15:18  abclzr  阅读(190)  评论(0编辑  收藏  举报