好玩但没啥用的$prufer$序列。
记$S$为有度数限制的点的集合,$cnt$为不属于$S$的点的数量,$sum=\sum\limits_{i\in S}d(i)-1$。
先把$S$中的点扔到$prufer$序列里,$C_{n-2}^{sum}$选好位置,序列数有$\dfrac{sum!}{\prod\limits_{i\in S}[d(i)-1]!}$种。
再把剩下的$cnt$个点扔进去,也就是剩下的$n-2-sum$个位置,每个位置有$cnt$种取值,即$cnt^{n-2-sum}$。
答案就是$C_{n-2}^{sum}\dfrac{sum!}{\prod\limits_{i\in S}[d(i)-1]!}cnt^{n-2-sum}$。注意判一下无解。
最后就是恶心的高精了。又双叒叕把别人的板子抄了过来
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 1005
#define inf 0x3f3f3f3f
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
int d[maxn];
#include <stack>
const int N=10000,B=3,base=1000;
struct long_long{
private:
int len,a[N];
inline void clear(){while(!a[len]&&len>1) --len;}
public:
long_long(){memset(a,0,sizeof a);len=0;}
long_long(int x){memset(a,0,sizeof a);a[len=1]=x;}
void print(){
printf("%d",a[len]);
for(int i=len-1;i>0;--i)
for(int j=base/10;j>0;j/=10) printf("%d",a[i]/j%10);
pn;
}
long_long &operator =(int x){
stack<char> st;string s;
if(!x) return *this="0";
while(x){st.push(x%10+'0');x/=10;}
while(!st.empty()) s+=st.top(),st.pop();
return *this=s;
}
long_long &operator =(const string &s){
memset(a,0,sizeof a);len=0;
int l=s.length();
for(int i=0;i<=l;++i){
int j=(l-i+(B-1))/B;
a[j]=(a[j]<<1)+(a[j]<<3)+(s[i]^48);
}
len=(l+(B-1))/B;
return *this;
}
long_long operator +(const long_long &x)const{
long_long res;res.len=max(len,x.len);int k=0;
for(int i=1;i<=res.len;++i){
res.a[i]=a[i]+x.a[i]+k;
k=res.a[i]/base;
res.a[i]%=base;
}
if(k>0) res.a[++res.len]=k;
return res;
}
long_long operator -(const long_long &x)const{
long_long res=*this;
for(int i=1;i<=len;++i){
res.a[i]-=x.a[i];
if(res.a[i]<0) --res.a[i+1],res.a[i]+=base;
}
res.clear();
return res;
}
long_long operator *(const int &x)const{
long_long res=*this;
for(int i=1;i<=len;++i) res.a[i]*=x;
for(int i=1;i<=len;++i) res.a[i+1]+=res.a[i]/base,res.a[i]%=base;
int &end=res.len;
while(res.a[end+1]>0){++end;res.a[end+1]+=res.a[end]/base,res.a[end]%=base;}
return res;
}
long_long operator *(const long_long &x)const{
long_long res;res.len=len+x.len;
for(int i=1;i<=len;++i)
for(int j=1;j<=x.len;++j){
res.a[i+j-1]+=a[i]*x.a[j];
res.a[i+j]+=res.a[i+j-1]/base;
res.a[i+j-1]%=base;
}
res.clear();
return res;
}
long_long operator /(const int &x)const{
long_long res;res.len=len;int k=0;
for(int i=len;i>0;--i){
k=k*base+a[i];
res.a[i]=k/x;
k%=x;
}
res.clear();
return res;
}
int operator %(const int &x)const{
int k=0;
for(int i=len;i>0;--i){
k=k*base+a[i];
k%=x;
}
return k;
}
bool operator <(const long_long &x)const{
if(len==x.len){
int i;
for(i=len;a[i]==x.a[i]&&i>1;--i);
if(i>=1) return a[i]<x.a[i];
return false;
}
return len<x.len;
}
bool operator >(const long_long &x)const{return !(*this<x);}
void operator += (const int &x){*this=*this+x;}
void operator *= (const int &x){*this=*this*x;}
void operator /= (const int &x){*this=*this/x;}
}ans=1;
int main(){
int n=read(),sum=0,cnt=0;
for(register int i=1;i<=n;++i){
d[i]=read();
if(d[i]==-1)++cnt;
else if(d[i]==0){puts("0");return 0;}
else sum+=d[i]-1;
}
if(n==1){printf("%d\n",d[1]==0?1:0);return 0;}
if(!n||sum>n-2){puts("0");return 0;}
for(register int i=n-2-sum+1;i<=n-2;++i)ans*=i;
for(register int i=2;i<=sum;++i)ans/=i;
for(register int i=2;i<=sum;++i)ans*=i;
for(register int i=1;i<=n-2-sum;++i)ans*=cnt;
for(register int i=1;i<=n;++i)
if(d[i]!=-1)for(register int j=2;j<d[i];++j)ans/=j;
ans.print();
}