BZOJ1005

来源:互联网 发布:企业查询软件 编辑:程序博客网 时间:2024/05/17 07:02

1005: [HNOI2008]明明的烦恼

思路:prufer编码
(HNOI2008都考的什么gui啊……)
仔细观察可得,树中每个点的度数,就是它在prufer序列里出现的次数+1
这下就变成了一个简单组合问题了
特判一下n=1和n=2
然而要写高精度……

代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <iostream>#include <algorithm>using namespace std;const int MAXN=1010,MAXP=300;int n,m,t;int d[MAXN];int prime[MAXN],top;bool check[MAXN];void eular(){    for (int i=2;i<=1000;i++) {        if (!check[i])            prime[++top]=i;        for (int j=1;j<=top;j++) {            if (i*prime[j]>1000) break;            check[i*prime[j]]=true;            if (i%prime[j]==0) break; }}    return ;}int jc[MAXN][MAXP],ans[MAXP];int out[MAXN*100];void init(){    eular();    cin>>n;    for (int i=1;i<=n;i++) {        scanf("%d",&d[i]);        t+= d[i]==-1 ? 0 : d[i]-1 ; }    if (n==1) {        if (d[1]==0 || d[1]==-1) cout<<1<<endl;        else cout<<0<<endl;        return ; }  if (n==2) {    if ((d[1]==-1 || d[1]==1) && (d[2]==-1 || d[2]==-1)) cout<<1<<endl;    else cout<<0<<endl;    return ; }    if (t>n-2) {        cout<<0<<endl;        return ; }    for (int i=2;i<=n;i++) {        int now=i,k=top;        while (k) {            jc[i][k]=jc[i-1][k];            while (now%prime[k]==0) {                jc[i][k]++;                now/=prime[k]; }            k--; }}    int b=n-2;    for (int i=1;i<=n;i++)        if (d[i]!=-1) {            m++;            int a=d[i]-1;            for (int j=1;j<=top;j++)                ans[j]+=jc[b][j]-jc[a][j]-jc[b-a][j];            b-=(d[i]-1); }    out[0]=out[1]=1;    for (int i=1;i<=top;i++)        for (int j=1;j<=ans[i];j++) {            for (int k=1;k<=out[0];k++)                out[k]*=prime[i];            for (int k=1;k<out[0];k++) {                out[k+1]+=out[k]/10;                out[k]%=10; }            while (out[out[0]]) {                out[out[0]+1]=out[out[0]]/10;                out[out[0]]%=10;                out[0]++; }            out[0]--; }    for (int i=1;i<=n-2-t;i++) {            for (int k=1;k<=out[0];k++)                out[k]*=n-m;            for (int k=1;k<out[0];k++) {                out[k+1]+=out[k]/10;                out[k]%=10; }            while (out[out[0]]) {                out[out[0]+1]=out[out[0]]/10;                out[out[0]]%=10;                out[0]++; }            out[0]--; }    for (int i=out[0];i>=1;i--)        printf("%d",out[i]);    return ;}int main(){    init();    return 0;}
0 0
原创粉丝点击