[题解] [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; 
}

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

原文地址:https://www.cnblogs.com/ztlztl/p/12199639.html