zoukankan      html  css  js  c++  java
  • Codeforces 382E Ksenia and Combinatorics 【组合计数】*

    Codeforces 382E Ksenia and Combinatorics


    Ksenia has her winter exams. Today she is learning combinatorics. Here’s one of the problems she needs to learn to solve.

    How many distinct trees are there consisting of n vertices, each with the following properties:

    the tree is marked, that is, the vertices of the tree are numbered from 1 to n;
    each vertex of the tree is connected with at most three other vertices, and at the same moment the vertex with number 1 is connected with at most two other vertices;
    the size of the tree’s maximum matching equals k.
    Two trees are considered distinct if there are such two vertices u and v, that in one tree they are connected by an edge and in the other tree they are not.

    Help Ksenia solve the problem for the given n and k. As the answer to the problem can be very huge you should output it modulo 1000000007 (109 + 7).

    Input

    The first line contains two integers n, k (1 ≤ n, k ≤ 50).

    Output

    Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).

    Examples

    input

    1 1

    output

    0

    input

    2 1

    output

    1

    input

    3 1

    output

    3

    input

    4 2

    output

    12

    Note

    If you aren’t familiar with matchings, please, read the following link: http://en.wikipedia.org/wiki/Matching_(graph_theory).


    简洁版题意:有n个节点的数,每个节点有不同的标号,求生成树匹配大小为k的方案数,其中除了根节点所有节点的度数不超过3,根节点1度数不超过2

    考虑DP计数吧
    dp[i][j][0/1]表示大小为i的子树,最大匹配是j,是否匹配当前节点的方案数
    然后当i==n的时候和左右子树大小相同的情况需要特判掉

    然后就是常规DP

    #include<bits/stdc++.h>
    using namespace std;
    #define yyf 1000000007
    #define N 60
    #define LL long long
    LL dp[N][N][2];
    LL C[N][N];
    void update(LL &a,LL b){a=(a+b)%yyf;}
    int main(){
        LL n,k;scanf("%lld%lld",&n,&k);
        if(k*2>n){printf("0");return 0;}
        for(LL i=0;i<=n;i++)C[i][0]=1;
        for(LL i=1;i<=n;i++)
            for(LL j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%yyf;
        dp[1][0][0]=dp[0][0][1]=1;
        for(LL siz=2;siz<=n;siz++)
            for(LL mac=1;mac<=k;mac++){
                //不匹配当前节点
                for(LL ls=0,rs=siz-1;ls<=rs;ls++,rs--){
                    for(LL lm=0,rm=mac;lm<=mac;lm++,rm--){
                        if(lm*2>ls||rm*2>rs)continue;
                        LL tmp=(ls==rs?C[siz-2][ls-1]:C[siz-1][ls])*(siz==n?1:siz)%yyf;//特判掉左边大小等于右边
                        update(dp[siz][mac][0],dp[ls][lm][1]*dp[rs][rm][1]%yyf*tmp%yyf);
                    }
                }
                //匹配当前节点
                for(LL ls=0,rs=siz-1;ls<=rs;ls++,rs--){
                    for(LL lm=0,rm=mac-1;lm<mac;lm++,rm--){
                        if(lm*2>ls||rm*2>rs)continue;
                        LL tmp=(ls==rs?C[siz-2][ls-1]:C[siz-1][ls])*(siz==n?1:siz)%yyf;
                        update(dp[siz][mac][1],dp[ls][lm][1]*dp[rs][rm][0]%yyf*tmp%yyf);
                        update(dp[siz][mac][1],dp[ls][lm][0]*dp[rs][rm][1]%yyf*tmp%yyf);
                        update(dp[siz][mac][1],dp[ls][lm][0]*dp[rs][rm][0]%yyf*tmp%yyf);
                    }
                }
            }
        printf("%lld",(dp[n][k][0]+dp[n][k][1])%yyf);
        return 0;
    }
  • 相关阅读:
    ubuntu20.04安装python pip
    linux tar包追加问题
    [Linux]主机无法ping通虚拟机,但虚拟机却可以ping通主机
    安装pygraphviz/graphviz报错
    elasticsearch Delete (根据条件删除)
    python2 vs python3的区别汇总
    python实现elasticsearch的update操作,不改变原数据,增加字段,或者查询更新
    python bulk批量保存elasticsearch数据
    python rpc 简单实现自带包xmlrpc
    Python获取当前运行函数的名称、类方法名称
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676322.html
Copyright © 2011-2022 走看看