1. 程式人生 > >BZOJ1005 HNOI2008明明的煩惱(prufer+高精度)

BZOJ1005 HNOI2008明明的煩惱(prufer+高精度)

const clu sum lld ans else con pre ||

  每個點的度數=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;
}

  

BZOJ1005 HNOI2008明明的煩惱(prufer+高精度)