AT3576 Popping Balls(计数)

AT3576 Popping Balls(计数)

题目大意

有A+B个球排成一行,其中左边A个是红色的,右边B个是蓝色的。你可以选定一对整数(s,t)(s<t),然后重复进行以下操作直到球被取完:将第一个球或第s个球或第t个球(当前球的数量必须够才能执行)拿出来。求最后拿出来的球的颜色序列有几种不同方案数,对1e9+7取模,方案不同当且仅当存在某一次取出的球的颜色不同。

数据范围

\[1 \le x, y \le 2000 \]

解题思路

一开始想了一个 \(\Theta(n^3)\) 的 dp,又想了半天优化结果大失败了😭

这题有几个显然的结论

开始不断的放球,如果要放红球,直接从第一个拿,下面我们讨论一下怎样拿蓝球

首先我们不要一开始选出 s 和 t,当要拿蓝球的时候在放,这样可以使以后更有可能用到这个点

所以答案就是 \(Ans = \sum_{i=1}^{A+1}\sum_{j=0}^{i-1}{B-1 \choose j}\sum_{k=1}^{i-j}\sum_{t=0}^{k-1}{j-1\choose t}\)

稍微优化一下就可以做到 \(\Theta(n^2)\) 了,但我这个 dp 做法可以做到 \(\Theta(n^3k)\),其中 k 是 s,t 这样的点的个数,k 增大时原方法可能会有些爆炸。具体怎么 dp 可以联系我,也可以看下面的代码。

/*
     />  フ
     |  ^  ^|
     /`ミ _x 彡
     /      |
    /   ヽ   ?
 / ̄|   | | |
 | ( ̄ヽ__ヽ_)_)
 \二つ
 */

#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template<typename F>
inline void write(F x, char ed = '\n') {
	static short st[30];short tp=0;
	if(x<0) putchar('-'),x=-x;
	do st[++tp]=x%10,x/=10; while(x);
	while(tp) putchar('0'|st[tp--]);
	putchar(ed);
}

template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }

template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }

const int N = 105;
const int P = 1e9 + 7;
int f[N][N][N][3], ans, x, y;
inline void add(int &x, int y) { x += y, x >= P && (x -= P); }
int main() {
	read(x), read(y); int lim = x + y + 1;
	f[x][y][lim][0] = 1;
	for (int i = x;i >= 0; i--) {
		for (int j = y;j >= 0; j--) {
			for (int k = i + 1;k <= lim; k++) {
				for (int t = 0;t <= 2; t++) {
					if (i) {
						add(f[i-1][j][k][t], f[i][j][k][t]);
						if (j && i + j >= k) add(f[i][j-1][k][t], f[i][j][k][t]);
						if (t < 2 && j && i + j < k) add(f[i][j-1][i+1][t+1], f[i][j][k][t]);
					}
					else if (j) add(f[i][j-1][k][t], f[i][j][k][t]);
				}
			}
		}
	}
	
	return 0;
}
posted @ 2020-09-10 19:43  Hs-black  阅读(136)  评论(1编辑  收藏  举报