[题解] [AGC013D] Piling Up

题面

题解

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

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

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

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

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

并且这是肯定可以实现的

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

转移的话是这样的

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

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

拿了两个白球

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

这次拿了先黑再白

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

这次拿了先白再黑

\(f[i - 1][j][0 / 1] \to 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\n", ans); 
	return 0; 
}

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

posted @ 2020-01-16 09:26  ztlztl  阅读(130)  评论(0编辑  收藏  举报