【组合数学】【高精度】【prufer数列】【HNOI 2008】【bzoj 1005】明明的烦恼

来源:互联网 发布:网络衣服 编辑:程序博客网 时间:2024/04/29 03:44

1005: [HNOI2008]明明的烦恼

Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3217  Solved: 1290

Description

自从明明学了树的结构,就对奇怪的树产生了兴趣…… 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树?

Input

第一行为N(0 < N < = 1000),接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1

Output

一个整数,表示不同的满足要求的树的个数,无解输出0

Sample Input

31-1-1

Sample Output

2

HINT

两棵树分别为1-2-3;1-3-2

题解:

苦颓了一中午。。各种不会啊。。于是膜拜了一下题解——>非常神
顺便学会了一种神奇的无根树的数列——>prufer数列
要写高精乘高精真是懒得写了,于是偷懒写了一个压位。。

Code:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define N 1010#define LL long long#define p 100000int n,m=0,s=0,d[N],su[N],ys[N],ans[N*10];int in(){    int x=0; char ch=getchar(); bool f=true;    while (ch<'0' || ch>'9'){        if (ch=='-') f=false;        ch=getchar();    }    while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();    if (!f) x=-x;    return x;}void init(){    for (int i=2; i<=N; i++){        bool f=true;        for (int j=2; j<=sqrt(i); j++)            if (!(i%j)){                f=false; break;            }        if (f) su[++su[0]]=i;    }}void cheng(int x){    for (int i=1; i<=ans[0]; i++) ans[i]*=x;    for (int i=1; i<=ans[0]; i++)        ans[i+1]+=ans[i]/p,ans[i]%=p;    while (ans[ans[0]+1]){        ans[0]++;        ans[ans[0]+1]+=ans[ans[0]]/p;        ans[ans[0]]%=p;    }}void fenjie(int x,int y){    for (int i=1; i<=x; i++){        int xx=i;        for (int j=1; j<=su[0]; j++){            if (xx<=1) break;            while (!(xx%su[j]))                ys[j]+=y,xx/=su[j];        }    }}void out(){    printf("%d",ans[ans[0]]);    for (int i=ans[0]-1; i>=1; i--)        printf("%05d",ans[i]);    printf("\n");}int main(){    n=in(); ans[++ans[0]]=1;    if (n==1){        int x=in();        if (!x) printf("1\n");        else printf("0\n");        return 0;    }    for (int i=1; i<=n; i++){        d[i]=in();        if (!d[i]){            printf("0\n");            return 0;        }        if (d[i]==-1) m++;        else d[i]--,s+=d[i];    }    if (s>n-2){        printf("0\n");        return 0;    }    init();    fenjie(n-2,1),fenjie(n-2-s,-1);    for (int i=1; i<=n; i++)        if (d[i]>0) fenjie(d[i],-1);    for (int i=1; i<=su[0]; i++)        while (ys[i]--) cheng(su[i]);    for (int i=1; i<=n-2-s; i++) cheng(m);    out();    return 0;}
1 0
原创粉丝点击