传送门:HTTP://www.lydsy.com/JudgeOnline/problem.php ID = 1211
题意:给你n个点和每个点的度求符合这些结构树的方案数
思路:参照http://blog.csdn.net/sinat_27410769/article/details/46596739
这里直接给出公式sum = sigma d [i] -1 ans = sum!/(d [1] -1)*(d [2] -1)* .... *(d [n] -1)
特别说明:n == 1 d [1] == 0需要特判
码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 160;
inline void read(int &x){x = 0;char p = getchar();while(!(p <= '9' && p >= '0'))p = getchar();while(p <= '9' && p >= '0')x *= 10, x += p - 48, p = getchar();}
LL prime[25100],is[25100],pricnt=0;
inline void init()
{
is[1]=1;
for(int i=2;i<=25000;i++)
{
if(is[i] == 0) prime[++pricnt]=i;
for(int j=1;j<=pricnt;j++)
{
if(i*prime[j] > 25000ll) break;
is[i*prime[j]]=1;
}
}
}
LL d[160];int n;
LL A[25010],B[25010];
LL mul(LL a,LL b)
{
LL c=1ll;
while(b > 0)
{
if(b&1) c*=a;
b>>=1;
a*=a;
}
return c;
}
void Fac(LL x,LL num[])
{
if(x == 0 || x == 1) return;
for(int i=1;i<=pricnt;i++)
{
while(x%prime[i] == 0) x/=prime[i],num[i]++;
if(x == 1) return;
}
}
int main()
{
init();
while(scanf("%d",&n)!=EOF)
{
int flag=0;LL sum=0;
memset(A,0,sizeof A);
memset(B,0,sizeof B);
for(int i=1;i<=n;i++)
{
scanf("%lld",&d[i]);
if(d[i] == 0) flag=1;
sum+=d[i]-1;
}
if(sum +n !=(n-1)*2ll) flag=1;
if(n == 1 && d[1] == 0) puts("1");
else if(flag == 1) puts("0");
else
{
LL ans=1ll;
for(LL i=1;i<=sum;i++) Fac(i,A);
for(int i=1;i<=n ;i++) Fac(d[i]-1ll,B);
for(int i=1;i<=pricnt;i++)
{
A[i]-=B[i];
ans*=mul(prime[i],A[i]);
}
printf("%lld\n",ans);
}
}
return 0;
}