• [bzoj1005][HNOI2008][明明的烦恼] (高精度+prufer定理)


    Description

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

    Input

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

    Output

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

    Sample Input

    3
    1
    -1
    -1

    Sample Output

    2

    HINT

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

    Solution

    填昨天的坑

    根据prufer定理,用排列组合推出ans=(n-2)!/[(D1-1)!(D2-1)!···(Dk-1)!left!] * m^left

    其中left=(n-2)-(D1-1)-(D2-1)-···-(Dk-1)

    哦,还要注意特判,当无解时,高精度数组长度为0,直接输出0就行了

    PoPoQQQ的代码很优雅

    Code:

    #include <stdio.h>
    #include <memory.h>
    #define ll long long
    struct num {
        int top;
        ll x[500];
        num(ll a=0) {
            memset(x,0,sizeof x );
            top=1;
            x[1]=a; }
        num operator*(const num b) {
            num tmp;
            for(int i=1; i<=top; i++)
                for(int j=1; j<=b.top; j++)
                    tmp.x[i+j-1]+=x[i]*b.x[j],
                    tmp.x[i+j]+=tmp.x[i+j-1]/100000000,
                    tmp.x[i+j-1]%=100000000;
            tmp.top=top+b.top;
            if(!tmp.x[tmp.top])
                tmp.top--;
            return tmp; } }ans(1);
    void Q_pow(int x,int p) {
        num tmp(x);
        for(;p;p>>=1,tmp=tmp*tmp)
            if(p&1)
                ans=ans*tmp; }
    int n,m,lef,cnt[1010];
    void factorZ(int x,int d) {
        for(int i=2;i*i<=x;i++)
            while(!(x%i))
                cnt[i]+=d,
                x/=i;
        if(x^1)cnt[x]+=d; }
    int main() {
        scanf("%d",&n);
        lef=n-2;
        for(int i=2;i<=lef;i++)
            factorZ(i,1);
        for(int i=1;i<=n;i++) {
            int x;
            scanf("%d",&x);
            if(~x) {
                if(x>1) {
                    lef-=x-1;
                    for(int i=2;i<=x-1;i++)
                        factorZ(i,-1); } }
            else ++m; }
        for(int i=2;i<=lef;i++)
            factorZ(i,-1);
        factorZ(m,lef);
        for(int i=2;i<=n;i++)
            if(cnt[i])
                Q_pow(i,cnt[i]);
        printf("%lld",ans.x[ans.top]);
        for(int i=ans.top-1;i;i--)
            printf("%08lld",ans.x[i]);
        return 0; }
  • 相关阅读:
    分享
    慕课网-软件测试基础-学习笔记
    向量内积(点乘)和外积(叉乘)概念及几何意义
    使用opencv3+python实现视频运动目标检测
    解决opencv3运行opencv2代码时报错的修改备忘录
    分享
    OpenCV学习笔记
    LeetCode
    LeetCode
    npm安装包很慢
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6274607.html
Copyright © 2020-2023  润新知