BZOJ1005: [HNOI2008]明明的烦恼

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1005

树的prufer编码是唯一的,然后推一发公式。(敲少一个字符调半天。。。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 100500
using namespace std;
int ans[1005000];
int pri[maxn],vis[maxn],num[maxn],d[maxn],x[maxn];
int tot,cnt,n,sum,gg,l;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void pre(){
    rep(i,2,1000){
        if (!vis[i]) vis[i]=1,pri[++tot]=i;
        rep(j,1,tot) {
            vis[i*pri[j]]=1;
            if (i*pri[j]>1000) break;
            if (i%pri[j]==0) break;
        }
    }
}
void get(int x,int v){
    int now=1;
    while (x!=1){
        while (x%pri[now]==0) num[now]+=v,x/=pri[now];
        now++;
    }   
}
int main(){
    pre();
    n=read();
    int len=n-2;
    rep(i,1,n){
        d[i]=read(); if (d[i]!=-1) cnt++,sum+=d[i]-1; 
        if (d[i]==0||len-(d[i]-1)<0) {gg=1; break;}
        if (d[i]!=-1) len-=d[i]-1;
    }
    if (gg) {puts("0"); return 0;}
    clr(num,0);
    rep(i,1,n-2) get(i,1);
    rep(i,1,n-2-sum) get(i,-1);
    rep(i,1,n){
        if (d[i]!=-1) rep(j,1,d[i]-1) get(j,-1);
    } 
    get(n-cnt,n-2-sum);
    l=1; x[1]=1;
    rep(i,1,tot){
        while (num[i]){
            num[i]--;
            rep(j,1,l) x[j]=x[j]*pri[i];
            rep(j,1,l) x[j+1]+=x[j]/10,x[j]=x[j]%10;
            while (x[l+1]>0) {l++; x[l+1]+=x[l]/10; x[l]%=10;  }
        }
    }
    while (x[l]==0) l--;
    down(i,l,1) printf("%d",x[i]);
    return 0;
}

 

posted on 2015-12-03 19:58  ctlchild  阅读(151)  评论(0编辑  收藏  举报

导航