[题解] [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的主要内容,如果未能解决你的问题,请参考以下文章