BZOJ1211: [HNOI2004]树的计数
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1211
依然是prufer编码,然后注意一下坑点。
#include<cstring> #include<cstdio> #include<algorithm> #include<iostream> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 100500 #define ll long long using namespace std; ll ans,d[maxn]; int pri[maxn],num[maxn],vis[maxn],tot,sum; int n; ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void pre(){ rep(i,2,200){ if (!vis[i]) vis[i]=1,pri[++tot]=i; rep(j,1,tot) { if (i*pri[j]>200) break; vis[i*pri[j]]=1; if (i%pri[j]==0) break; } } } void get(int x,int v){ int now=1; while (x!=1){ while (x%pri[now]==0) x/=pri[now],num[now]+=v; now++; } } int main(){ pre(); scanf("%d",&n); int len=n-2; int gg=0; rep(i,1,n){ d[i]=read(); if (d[i]==0) {gg=1; break;} sum+=d[i]-1; } if (n==1&&!d[1]) {puts("1"); return 0;} if (sum!=len) gg=1; if (gg) {puts("0"); return 0;} ans=1; rep(i,1,sum) get(i,1); rep(i,1,n) { rep(j,1,d[i]-1) get(j,-1); } rep(i,1,tot) if (num[i]) { rep(j,1,num[i]) ans=ans*(ll)pri[i]; } printf("%lld\n",ans); return 0; }