zoukankan      html  css  js  c++  java
  • acdream1412:2-3 trees 组合数dp

    题意:

    给出一个标准2-3树的叶子节点(最底层节点)个数 L,求2-3数的形成方案数并取余

    分析:

    如果有L个叶子
    枚举 每个 可以使x*2+y*3=L 的 x y

    那么在最底层就有  c(x+y,x)种  2,3的放法
    上一层就是有 x+y个叶子的子问题 这样就可以递推算了

    枚举时首先注意到 x=L y=-L 是一组特解,因此可以由它求出所有的通解

    提前处理出组合数。

    然后对于每组合法的解通过dp转移即可

    代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    using namespace std;
    #define MAXN 10000
    const int mm =1000000007;
    int c[2510][2510];
    long long dp[5010];
    long long L,r;
    void ini()
    {
        memset(c,0,sizeof(c));
        c[0][0]=1;
        c[1][0]=c[1][1]=1;
        for(int i=2;i<=L/2;i++)
        {
            c[i][0]=1;
            for(int j=1;j<i;j++)
            {
                c[i][j]=(c[i-1][j-1]%r+c[i-1][j]%r)%r;
            }
            c[i][i]=1;
        }
    }
    void solve()
    {
        dp[1]=1;
        dp[2]=1;
        dp[3]=1;
        for(int i=4;i<=L;i++)
        {
            dp[i]=0;
            int x=-i,y=i;
            x=(x%3+3)%3;
            y=(i-x*2)/3;
            while(x*2<=i)
            {
                int k=x>y?y:x;
                dp[i]=(dp[i]+((long long)c[x+y][k]*dp[x+y])%r)%r;
                x+=3;
                y-=2;
            }
        }
        printf("%lld
    ",dp[L]);
    }
    int main()
    {
        //freopen("shu.txt","r",stdin);
        while(scanf("%lld%lld",&L,&r)!=EOF)
        {
            ini();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    Python 函数装饰器简明教程
    *arg和**kwarg的区别
    克里金插值
    C语言Hello world
    ibatis错误
    typealias
    视图
    权限分级设置
    走出浮躁的泥沼:学会享受学习过程的乐趣
    R语言 eval(quote(x)) 和 eval(x)
  • 原文地址:https://www.cnblogs.com/oneshot/p/4004717.html
Copyright © 2011-2022 走看看