[BZOJ1005][HNOI2008]明明的烦恼(树的purfer序列+高精度)

来源:互联网 发布:淘宝客广告语 编辑:程序博客网 时间:2024/05/13 23:58

题目描述

传送门

题解

参考资料:
http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html
http://hzwer.com/3272.html
也就是说,一种purfer序列只能对应一颗生成树,那么求生成树的个数就是求不同的purfer序列的个数。
那么利用组合公式可以推出求出不同purfer序列的公式。
显然这个数非常大,牵扯到高精度,那么我们可以十分机智地将分数线上下分解质因数,然后做高精度乘法即可。

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int max_n=1005;int n,sum,cnt,q,temp;int c[max_n],d[max_n],pri[max_n];struct hp{int a[100000];}ans;inline void cheng(hp &ans,int b){    for (int i=1;i<=ans.a[0];++i) ans.a[i]*=b;    for (int i=1;i<=ans.a[0];++i)    {        ans.a[i+1]+=ans.a[i]/10;        ans.a[i]%=10;    }    while (ans.a[ans.a[0]+1])    {        ans.a[0]++;        ans.a[ans.a[0]+1]+=ans.a[ans.a[0]]/10;        ans.a[ans.a[0]]%=10;    }}int main(){    scanf("%d",&n);    if (n==1)    {        scanf("%d",&c[1]);        if (c[1]==0||c[1]==-1) printf("1\n");        else printf("0\n");        return 0;    }    for (int i=1;i<=n;++i)    {        scanf("%d",&c[i]);        if (!c[i])        {            printf("0\n");            return 0;        }        if (c[i]!=-1)        {            d[++cnt]=c[i]-1;            sum+=d[cnt];        }        else q++;       }    if (n-2<sum)    {        printf("0\n");        return 0;    }    for (int i=1;i<=cnt;++i)        for (int j=2;j<=d[i];++j)        {            temp=j;            for (int k=2;k<=j&&temp!=1;++k)                while (temp%k==0) pri[k]--,temp/=k;        }    for (int i=n-2-sum+1;i<=n-2;++i)    {        temp=i;        for (int j=2;j<=i&&temp!=1;++j)            while (temp%j==0) pri[j]++,temp/=j;    }    ans.a[0]=1; ans.a[1]=1;    for (int i=1;i<=n;++i)        while (pri[i])        {            pri[i]--;            cheng(ans,i);        }    for (int i=1;i<=n-2-sum;++i)        cheng(ans,q);    for (int i=ans.a[0];i>=1;--i)        printf("%d",ans.a[i]);    putchar('\n');}

总结

分解质因数的姿势注意一下。

0 0