树的prufer编码,具体内容见黄学长博客。。。
http://hzwer.com/3272.html
实现小技巧就是开全局数组记答案各质因数的次数最后统一乘,只有bign*int 所以可以压位
<del>然而数据规模太小所以我什么优化都没有加
#include<cstdlib> #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define maxn 1005 void _read(int &x) { x=0; char ch=getchar(); bool flag=false; while(ch<'0' || ch>'9'){if(ch=='-')flag=1; ch=getchar();} while(ch>='0' && ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x; return ; } int n,cnt,sum,d[maxn],pre_cnt,pre[2*maxn],a[2*maxn],b[2*maxn]; bool v[2*maxn],wrong; void getpre(int T)//分解质因数的准备工作 { memset(v,0,sizeof(v)); for(int i=2;i<=T;i++)if(!v[i]) { pre[++pre_cnt]=i; for(int j=i;j*i<=T;j++)v[j*i]=1; } return ; } void Init() { wrong=false; _read(n); sum=0;cnt=0; for(int i=1;i<=n;i++)_read(d[i]); for(int i=1;i<=n;i++)if(d[i]==0){wrong=true;return;} for(int i=1;i<=n;i++)if(d[i]!=-1){cnt++,sum+=(d[i]-1);} getpre(2000); return ; } void fj(int now)//将某个数的阶乘唯一分解 { int t=0; memset(b,0,sizeof(b)); if(now==1)return ; for(int i=1;i<=pre_cnt;i++) { t=pre[i]; while(t<=now){b[i]+=now/t; t=t*pre[i];} } return ; } void getC(int x,int y) { fj(y);for(int i=1;i<=pre_cnt;i++)a[i]+=b[i]; fj(x);for(int i=1;i<=pre_cnt;i++)a[i]-=b[i]; fj(y-x);for(int i=1;i<=pre_cnt;i++)a[i]-=b[i]; return ; } void getA() { fj(sum);for(int i=1;i<=pre_cnt;i++)a[i]+=b[i]; for(int j=1;j<=n;j++)if(d[j]-1>0) { fj(d[j]-1); for(int i=1;i<=pre_cnt;i++)a[i]-=b[i]; } return ; } void getPower() { memset(b,0,sizeof(b)); if(cnt<n) { int t=n-cnt; for(int i=1;i<=pre_cnt;i++) { if(t<=1)break; while(t%pre[i]==0 && t>0){b[i]++; t=t/pre[i];} } for(int i=1;i<=pre_cnt;i++)b[i]*=(n-2-sum); } for(int i=1;i<=pre_cnt;i++)a[i]+=b[i]; return ; } struct bign { int a[4005],n; bign() { memset(a,0,sizeof(a)); n=1; a[1]=1; } friend bign operator *(bign x,int y) { bign b; b.n=x.n+5; for(int i=1;i<=b.n;i++)b.a[i]=x.a[i]*y; for(int i=1;i<=b.n;i++)if(b.a[i]>=10){b.a[i+1]+=b.a[i]/10; b.a[i]=b.a[i]%10;} while(b.a[b.n]==0)b.n--; return b; } }ans; void Output() { for(int i=1;i<=pre_cnt;i++) { for(int j=1;j<=a[i];j++)ans=ans*pre[i]; } for(int i=ans.n;i>=1;i--)putchar(ans.a[i]+'0'); putchar('\n'); return ; } void work() { memset(a,0,sizeof(a));//a数组记录答案中各质因数的次数 //计算组合数 getC(sum,n-2); //计算可重集排列 getA(); //计算无限制项 getPower(); Output(); return ; } int main() { freopen("in.txt","r",stdin); Init(); if(n==1) { if(d[1]==0)printf("1\n"); else printf("0\n"); return 0; } if(sum<=n-2 && wrong==false)work(); else printf("0\n"); return 0; }