P2290 题解
前置知识:
prufer 序列。
思路:
我们都知道,prufer 序列有以下性质:
-
可以与树互相转化。
-
对于
n 个点的树,转化成 prufer 序列后序列里有n-2 个元素。 -
对于树上一个点,它在 prufer序列中的出现次数是它在树中的度数减去
1 。
根据这些性质,我们可以转换问题:
构造一棵树转化为构造一个 prufer 序列。
那么就成了多重集的全排列问题:
套公式就是:
但是我们正常算可能会溢出,所以我们用一个模数(
代码:
#include<bits/stdc++.h>
#define int __int128//因为1e17*1e17爆long long,所以用它
using namespace std;
const int cxk=155,mod=100000000000000003ll;
int fastpow(int x,int y)
{
int lcq=1,pw=x%mod;
for(int i=0;i<=62;i++,pw=pw*pw%mod)
if(y>>i&1)
lcq=lcq*pw%mod;
return lcq;
}
int read()//输入
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void print(int x)//输出
{
if(x<=9)
cout<<(signed)(x);
else
{
print(x/10);
cout<<(signed)(x%10);
}
}
int jc[cxk],n,deg[cxk],sum;
signed main()
{
n=read();
if(n==0)//特判一下
cout<<1,exit(0);
jc[0]=1;//0的阶乘等于1
for(int i=1;i<=n;i++)
{
jc[i]=jc[i-1]*i%mod;//算阶乘
deg[i]=read();
sum+=deg[i];
if((deg[i]<1&&n!=1)||deg[i]>=n)
cout<<0,exit(0);
}
if(sum!=n*2-2)
cout<<0,exit(0);
int ans=jc[n-2];
for(int i=1;i<=n;i++)
ans=ans*fastpow(jc[deg[i]-1],mod-2)%mod;//乘逆元
print(ans);
}