[题解] [AGC013D] Piling Up

Posted ztlztl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解] [AGC013D] Piling Up相关的知识,希望对你有一定的参考价值。

题面

题解

把操作放到坐标轴上, (y) 轴代表黑球个数, (x) 球代表操作次数

然后对应的操作就可以看作加上 ((1, 1))((1, -1)) 的两个向量

于是对应的操作序列就变为了一根折线

但是有可能会有重复的情况

我们只计算到达过 (x) 轴的那一根

并且这是肯定可以实现的

于是我们设 (f[i][j][0 / 1]) 代表前 (i) 次操作, 黑球还有 (j) 个, 没有 / 有经过 (0)

转移的话是这样的

假如说这次拿出了两个黑球

(f[i - 1][j][1] o f[i][j - 1][1] (j geq 1)) , (f[i - 1][j][0] o f[i][j - 1][0] (j geq 2)) , (f[i - 1][j][0] o f[i][j - 1][1] (j = 1))

拿了两个白球

(f[i - 1][j][0 / 1] o f[i][j + 1][0 / 1] (j < n))

这次拿了先黑再白

(f[i - 1][j][1] o f[i][j][1] (j leq 1)) , (f[i - 1][j][0] o f[i][j][0] (j leq 2)) , (f[i - 1][j][0] o f[i][j][1] (j = 1))

这次拿了先白再黑

(f[i - 1][j][0 / 1] o f[i][j][0 / 1] (j < n))

答案就是 (sum_{j = 0}^{n} f[m][j][1])

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
const int N = 3005;
const int mod = 1000000007; 
using namespace std;

int n, m, f[N][N][2], ans; 

template < typename T >
inline T read()
{
    T x = 0, w = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * w; 
}

int main()
{
    n = read <int> (), m = read <int> ();
    for(int i = 1; i <= n; i++)
        f[0][i][0] = 1;
    f[0][0][1] = 1;
    for(int i = 1; i <= m; i++)
        for(int j = 0; j <= n; j++)
        {
            if(!j)
            {
                f[i][j][1] = f[i - 1][j][1];
                if(j < n) f[i][j][1] = (1ll * f[i][j][1] + f[i - 1][j + 1][1] + f[i - 1][j + 1][0]) % mod; 
            }
            else if(j == 1)
            {
                if(j < n) f[i][j][0] = (f[i][j][0] + f[i - 1][j + 1][0] + f[i - 1][j][0]) % mod; 
                f[i][j][1] = (1ll * f[i - 1][j][1] + f[i - 1][j][0] + f[i - 1][j - 1][1]) % mod;
                if(j < n) f[i][j][1] = (1ll * f[i - 1][j + 1][1] + f[i][j][1] + f[i - 1][j][1]) % mod; 
            }
            else
            {
                f[i][j][0] = (1ll * f[i - 1][j][0] + f[i - 1][j - 1][0]) % mod; 
                f[i][j][1] = (1ll * f[i - 1][j][1] + f[i - 1][j - 1][1]) % mod;
                if(j < n)
                {
                    f[i][j][0] = (1ll * f[i][j][0] + f[i - 1][j][0] + f[i - 1][j + 1][0]) % mod;
                    f[i][j][1] = (1ll * f[i][j][1] + f[i - 1][j][1] + f[i - 1][j + 1][1]) % mod;
                }
            }
        }
    for(int i = 0; i <= n; i++)
        ans = (1ll * ans + f[m][i][1]) % mod; 
    printf("%d
", ans); 
    return 0; 
}

在洛谷上蒯的第一篇题解的转移方程, 不想写了

以上是关于[题解] [AGC013D] Piling Up的主要内容,如果未能解决你的问题,请参考以下文章

agc026 题解

AGC025简要题解

AGC 043 C,D 题解

AGC009题解

AGC 051 D C4 题解

AGC002 简要题解