当前位置: 代码迷 >> 综合 >> 【HNOI2008】bzoj1005 明明的烦恼
  详细解决方案

【HNOI2008】bzoj1005 明明的烦恼

热度:97   发布时间:2024-01-13 10:36:48.0

把树转化为purfer序列,问题就转化为了把 n 个元素放到 n?2 个位置上,有些元素的出现次数有限制,求方案数。
注意答案不取模,可以用指数加减来实现高精度除法。

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=2010,mod=1000;
int n,m,s,tot,a[maxn],vis[maxn],prm[maxn];
struct big
{int a[10010],l;void zero(){l=1;a[1]=0;}void one(){l=1;a[1]=1;}big operator * (const int &b) const{big ret;ret.zero();for (int i=1;i<=l;i++){ret.a[i]+=a[i]*b;ret.a[i+1]=ret.a[i]/mod;ret.a[i]%=mod;}ret.l=l+1;if (!ret.a[ret.l]) ret.l--;else while (ret.a[ret.l]>=mod){ret.a[ret.l+1]=ret.a[ret.l]/mod;ret.a[ret.l]%=mod;ret.l++;}return ret;}void out() const{printf("%d",a[l]);for (int i=l-1;i;i--){if (a[i]<100) putchar('0');if (a[i]<10) putchar('0');printf("%d",a[i]);}}
}ans;
struct inte
{int q[maxn],l;inte operator * (const inte &in) const{inte ret;ret.l=max(l,in.l);for (int i=1;i<=ret.l;i++) ret.q[i]=0;for (int i=1;i<=l;i++) ret.q[i]+=q[i];for (int i=1;i<=in.l;i++) ret.q[i]+=in.q[i];return ret;}inte operator / (const inte &in) const{inte ret;ret.l=max(l,in.l);for (int i=1;i<=ret.l;i++) ret.q[i]=0;for (int i=1;i<=l;i++) ret.q[i]+=q[i];for (int i=1;i<=in.l;i++) ret.q[i]-=in.q[i];return ret;}big get() const{big ret;ret.one();for (int j=1;j<=l;j++)for (int k=1;k<=q[j];k++)ret=ret*prm[j];return ret;}
}x[maxn],fac[maxn],tem;
int main()
{//freopen("bzoj_1005.in","r",stdin);//freopen("bzoj_1005.out","w",stdout);int y,mx=0;scanf("%d",&n);if (n==1){scanf("%d",&y);if (y==0||y==-1) printf("1\n");else printf("0\n");return 0;}for (int i=1;i<=n;i++){scanf("%d",&y);if (y==0){printf("0\n");return 0;}if (y!=-1){a[++m]=y-1;s+=y-1;mx=max(mx,y-1);}}if (s>n-2){printf("0\n");return 0;}for (int i=2;i<=n-2;i++){if (!vis[i]) prm[++tot]=i;for (int j=1;j<=tot&&(LL)i*prm[j]<=n-2;j++){vis[i*prm[j]]=1;if (i%prm[j]==0) break;}}for (int i=1;i<=n-2;i++){y=i;for (int j=1;y>1;j++)while (y%prm[j]==0){x[i].l=j;y/=prm[j];x[i].q[j]++;}}for (int i=1;i<=n-2;i++) fac[i]=fac[i-1]*x[i];tem=fac[n-2];for (int i=1;i<=m;i++) tem=tem/fac[a[i]];tem=tem/fac[n-2-s];ans=tem.get();for (int i=1;i<=n-2-s;i++) ans=ans*(n-m);ans.out();
}