• 【AGC013D】Pilling Up dp


    Description

    红蓝球各无限多个.
    初始时随意地从中选择 n 个, 扔入箱子
    初始有一个空的序列
    接下来依次做 m 组操作, 每组操作为依次执行下述三个步骤
    (1) 从箱子中取出一个求插入序列尾
    (2) 往箱子里补充 一红一蓝
    (3) 从箱子中取出一个求插入序列尾
    求 mm 次操作后, 有多少种不同的颜色序列, 答案对 109+7 取模

    Input

    第一行两个数 n,mn,m .

    Output

    一个数 ans 表示答案对 10^9+7 取模的值.

    Sample Input

    # 样例输入1
    
    2 3
    
    # 样例输入2
    
    1000 10
    
    # 样例输入3
    
    1000 3000
    

    Sample Output

    # 样例输出1
    
    56
    
    # 样例输出2
    
    1048576
    
    # 样例输出3
    
    693347555
    

    HINT

    样例解释1
    一共有 6 个球会被从盒子中取出.
    一个方案是不合法的当且仅当第 2,3,4,5 个球的颜色完全相同.

    所以答案为 26−23=56

    数据范围

    n,m≤3000

    Sol

    定义(f[i][j])为进行i轮,红球j个的方案数,然后跑普及组dp,但是这样会重复,原因:一个最终序列可能是由多个初始集合生成的。但是我们发现,如果开始有i个红球能够生成一个序列,i+j个也可以,那么我们找到这个最小的i,可以发现一定会用完,所以再加一维([0/1])表示有没有用完过红球,然后就不会有重复了。

    Code

    #include <cstdio>
    int n,m,f[3005][3005][2],ans;const int P=1e9+7;
    int main()
    {
        scanf("%d%d",&n,&m);f[0][0][1]=1;
        for(int i=1;i<=n;i++) f[0][i][0]=1;
        for(int i=0;i<m;i++) for(int j=0;j<=n;j++) for(int k=0;k<=1;k++)
        {
            if(j) f[i+1][j-1][k|!(j-1)]=(f[i+1][j-1][k|(j==1)]+f[i][j][k])%P;
            if(n-j) f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k])%P;
            if(j) f[i+1][j][k|(j==1)]=(f[i+1][j][k|(j==1)]+f[i][j][k])%P;
            if(n-j) f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%P;
        }
        for(int i=0;i<=n;i++) ans=(ans+f[m][i][1])%P;
        printf("%d
    ",ans);
    }
    
    
  • 相关阅读:
    合并、媒体查询
    混入、命名空间(less)、继承
    函数(内置函数 和 自定义函数)
    运算、单位、转义、颜色
    选择器嵌套、伪类嵌套、属性嵌套(只在Sass中)
    注释、变量、插值、作用域
    二路归并排序java实现
    堆排序Java实现
    和为S的连续正数序列——牛客网(剑指offer)
    transient 与 volatile 笔记
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9469383.html
Copyright © 2020-2023  润新知