[BZOJ1211]: [HNOI2004] tree count (Prufer sequence)

Topic Portal


Title Description

A tree of n nodes, each node provided it is $ v_1, v_2, ..., v_n $, known in the i-th node degree is $ V_I $ $ $ D_i, Q satisfying such a condition different how many trees trees. Given n, $ d_1, d_2, ..., d_n $, the programming required to meet the number of output $ d_ {v_i} = d_i $ tree.


Input Format

The first line is a positive integer n, the tree has n nodes. The second row has the number n, denotes the i-th $ d_i $, i.e. the i-th tree node degree.


Output Format

Output to meet the conditions of the tree how many trees.


Sample

Sample input

4
2 1 2 1

Sample Output

2


Data range and tips

$1 \leqslant n \leqslant 150$。

Ensure that the input data satisfies the condition of the tree does not exceed $ ^ {10} {17} $ a.


answer

The board is clearly a problem prufer sequence, the degree n points are determined for $ d_1, d_2, ... $ root of the tree no number: $ \ frac {(d_1-1) {(n-2)!} ! \ times (d_2-1)! \ times ...} $

However, note that two special sentence:

  1. To satisfy the tree is a $ \ sum \ limits_ {i = 1} ^ {n} d_i = 2 \ times n-2 $.

  2. When $ n = 1 $ obviously inconvenient to handle, can be directly output 1.

Direct output "0" you will be pleasantly surprised to find that you have 15 minutes!

As for the implementation, a high refinement for violence may be used, of course, also possible to use decomposition of the quality factor, the latter apparently achieved better.


Code time

#include<bits/stdc++.h>
using namespace std;
int n;
int d[151];
int pre[400],pri[400];
long long wzc[400];
long long ans=1LL;
void pre_work()//预处理质因数
{
	for(int i=2;i<=2*n;i++)
	{
		if(!pri[i])
		{
			pri[i]=i;
			pre[++pre[0]]=i;
		}
		for(int j=1;j<=pre[0];j++)
		{
			if(pre[j]>pri[i]||i*pre[j]>n)break;
			pri[i*pre[j]]=pre[j];
		}
	}
}
long long qsm(long long x,long long y)
{
	long long rec=1;
	while(y)
	{
		if(y&1)rec*=x;
		x*=x;
		y>>=1;
	}
	return rec;
}
int main()
{
	scanf("%d",&n);
	pre_work();
	int sum=0;
	bool flag=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&d[i]);
		if(!d[i])flag=1;
		sum+=d[i];
	}
	if(n==1&&!d[1]){puts("1");return 0;}
	if(sum!=2*n-2||flag){puts("0");return 0;}//两个特判
	for(int i=1;i<=n-2;i++)
	{
		int flag=i;
		while(flag>1)
		{
			wzc[pri[flag]]++;
			flag/=pri[flag];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<d[i];j++)
		{
			int flag=j;
			while(flag>1)
			{
				wzc[pri[flag]]--;
				flag/=pri[flag];
			}
		}
	}
	for(int i=1;i<=n;i++)
		if(wzc[i])ans=ans*qsm(i,wzc[i]);//计算答案
	printf("%lld",ans);
	return 0;
}

rp ++

Guess you like

Origin www.cnblogs.com/wzc521/p/11222183.html