BZOJ1005 HNOI2008明明的烦恼(prufer+高精度)

  每个点的度数=prufer序列中的出现次数+1,所以即每次选一些位置放上某个点,答案即一堆组合数相乘。记一下每个因子的贡献分解一下质因数高精度乘起来即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,a[N],f[N],g[N],ans[N<<2];
int main()
{
#ifndef ONLINE_JUDGE
	freopen("bzoj1005.in","r",stdin);
	freopen("bzoj1005.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	n=read();
	for (int i=1;i<=n;i++) a[i]=read()-1;
	for (int i=1;i<=n;i++) if (a[i]==-1) {cout<<0;return 0;}
	int sum=0;for (int i=1;i<=n;i++) if (a[i]==0) sum+=a[i];
	if (sum>n-2){cout<<0;return 0;}sum=n-2;int cnt=0;
	for (int i=1;i<=n;i++)
	if (a[i]>=0)
	{
		for (int j=sum-a[i]+1;j<=sum;j++) f[j]++;
		for (int j=1;j<=a[i];j++) f[j]--;
		sum-=a[i];
	}
	else cnt++;
	f[cnt]+=sum;
	for (int i=2;i<=n;i++)
	{
		int x=i;
		for (int j=2;j<=x;j++)
		while (x%j==0) g[j]+=f[i],x/=j;
		if (x>1) g[x]+=f[i];
	}
	ans[1]=1;int len=1;
	for (int i=2;i<=n;i++)
	while (g[i]--)
	{
		for (int j=1;j<=len;j++) ans[j]*=i;
		for (int j=1;j<=len;j++)
		ans[j+1]+=ans[j]/10,ans[j]%=10;
		while (ans[len+1]) len++,ans[len+1]+=ans[len]/10,ans[len]%=10;
	}
	for (int i=len;i>=1;i--) printf("%d",ans[i]);
	return 0;
}

  

posted @ 2019-02-17 20:59  Gloid  阅读(128)  评论(0编辑  收藏  举报