题解
首先我们要知道一条性质,prufer序列中的某个点出现次数为该点在树中度数-1
感性理解一下,其实按照prufer序列求法自己推一下就出来了
设题目里给的度为$d[]$
先将所有的d--
然后按照排列组合得出来
这是多重集排列数
首先从n-2中选择d[1]个数是$C_{n}^{d[1]}$然后再从剩余n-d[1]中选d[2] $C_{n-d[1]}^{d[2]}$依次类推
$C_{n-2}^{d[1]}\times C_{n-2-d[1]}^{d[2]}\times C_{n-2-d[1]-d[2]}^{d[3]}\times ……\times C_{n-2-d[1]-……-d[n-1]}^{d[n]}$
得到
$\frac{(n-2)!}{\sum\limits_{i=1}^{n}d[i]!}$
高精转移就完了
还是过不了?
一些特判:
首先该题会有无解的情况
然后当只有一个点时方案数为1
然后当出现度数为0的点时方案数要特殊处理
以下是本人丑陋的代码
#include<bits/stdc++.h> #define ll long long #define N 10 #define P 1 using namespace std; ll n,m,d[20000],cnt=0; bool flag[20000]; struct bignum {ll n[200000],l;bignum(){l=1,memset(n,0,sizeof(n));}void clear(){while(l>1&&!n[l-1]) l--;}void print(){printf("%lld",n[l-1]);for(ll i=l-2;i>=0;i--)printf("%0*lld",P,n[i]);printf("\n");}bignum operator = (ll x){l=0; while(x){n[l++]=x%N;x/=N;}return *this;}bignum operator +(bignum x) const{bignum t=*this;if(x.l>t.l) t.l=x.l; for(ll i=0;i<t.l;i++){t.n[i]+=x.n[i];if(t.n[i]>=N){t.n[i+1]+=t.n[i]/N;t.n[i]%=N;}}return t;}bignum operator * (const ll& b){bignum c;c.l=0;for(ll i=0,g=0;g||i<l;i++){ll x;if(i<l)x=n[i]*b+g;else x=g;c.n[c.l++]=x%N;g=x/N;}return c;}bignum operator *(bignum x) const{bignum t=*this,tep;tep.l=t.l+x.l+1;for(ll i=0;i<t.l;i++)for(ll j=0;j<=x.l;j++){tep.n[i+j]+=t.n[i]*x.n[j];}for(ll i=0;i<tep.l;i++){tep.n[i+1]+=tep.n[i]/N;tep.n[i]%=N;}tep.clear();return tep;}bool operator <(bignum x) const{bignum t=*this,tep;if(t.l!=x.l) return t.l<x.l;for(ll i=t.l-1;i>=0;i--){if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i];}return 0;}bool operator >(bignum x) const{bignum t=*this;if(t.l!=x.l) return t.l>x.l;for(ll i=t.l-1;i>=0;i--){if(t.n[i]!=x.n[i]) return t.n[i]>x.n[i];}return 0;}bignum operator -(bignum x) const{bignum t=*this;if(t<x) printf("-"),swap(t,x);ll jie=0;for(ll i=0;i<t.l;i++){t.n[i]-=x.n[i];while(t.n[i]<0){t.n[i]+=N;jie++;}t.n[i+1]-=jie;jie=0;;}t.clear();return t;}bignum operator /(const ll &x){bignum t=*this,r;ll tmp=0;r.l=t.l;for(ll i=t.l-1;i>=0;i--){tmp+=t.n[i];if(tmp>=x){r.n[i]=tmp/x;tmp%=x;}tmp*=N;}r.clear();return r;} }ans; bignum jie(ll x) {bignum t;t=1;for(ll i=2;i<=x;i++){t=x*i;}return t; } int main() {memset(flag,0,sizeof(flag));ll sum=0,you0=0;scanf("%lld",&n);for(ll i=1;i<=n;i++){scanf("%lld",&d[i]);if(d[i])flag[i]=1,cnt++;else you0=1;d[i]--,sum+=d[i];}if(you0&&n==1){cout<<1<<endl;return 0;}if(sum!=n-2||you0) {cout<<0<<endl;return 0;}ans=1;for(ll i=2;i<=cnt-2;i++)ans=ans*i;for(ll i=1;i<=n;i++){if(flag[i])for(ll j=2;j<=d[i];j++)ans=ans/j;}ans.print(); }