您的位置:首页 > 其它

[HNOI2004]树的计数

2017-10-07 21:47 218 查看

题目描述



输入输出格式

输入格式:

输入文件第一行是一个正整数n,表示树有n个结点。第二行有n个数,第i个数表示di,即树的第i个结点的度数。其中1<=n<=150,输入数据保证满足条件的树不超过10^17个。

输出格式:

输出满足条件的树有多少棵。

输入输出样输入样例#1:

4
2 1 2 1


输出样例#1:

2

Prüfer编码与Cayley公式

给出几个链接:

http://www.matrix67.com/blog/archives/682

http://blog.csdn.net/justesss/article/details/38129101

http://blog.csdn.net/yuyanggo/article/details/49951597

[b]总的来说,就是说:[/b]

[b]1.n个节点的生成树有n^(n-2)[/b]

[b]2.对于n个点,度为di[/b]

[b]方案数=(n-2)!/(∏(di-1)!)[/b]

[b]对于这题直接套第2个公式[/b]

[b]分解质因子再化简[/b]

[b]注意判断树能否构成[/b]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int d[1001],n,vis[1001],prime[1001],pre[1001],tot,sum;
long long s[1001],ans;
long long qpow(long long x,int y)
{
long long res=1;
while (y)
{
if (y&1) res=res*x;
x=x*x;
y=y/2;
}
return res;
}
int main()
{
int i,j;
cin>>n;
for (i=1; i<=n; i++)
{
scanf("%d",&d[i]);
if (d[i]==0&&1!=n)
{
cout<<0;
return 0;
}
sum+=d[i]-1;
for (j=2; j<=d[i]-1; j++)
s[j]--;
}
if (sum!=n-2)
{
cout<<0;
return 0;
}
for (i=2; i<=n-2; i++)
s[i]++;
for (i=2; i<=n; i++)
{
if (vis[i]==0)
{
pre[i]=i;
tot++;
prime[tot]=i;
}
for (j=1; j<=tot; j++)
{
if (prime[j]*i>n) break;
vis[i*prime[j]]=1;
pre[i*prime[j]]=prime[j];
if (i%prime[j]==0) break;
}
}
ans=1;
for (i=n; i>=2; i--)
if (pre[i]!=i)
{
s[pre[i]]+=s[i];
s[i/pre[i]]+=s[i];
s[i]=0;
}
for (i=n; i>=2; i--)
{
if (s[i]<0)
{
cout<<0;
return 0;
}
ans*=qpow(i,s[i]);
}
cout<<ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: