蒟蒻__stdcall终于更新博客辣~

一下午+一晚上=一道计数题QAQ

为什么计数题都这么玄学啊QAQ


Prelude

题目链接:这里是传送门= ̄ω ̄=

下面我将分几个步骤讲一下这个题的做法,大家不必一次看完,可以一点一点地推进思路,希望对锻炼大家的思维能力有帮助o( ̄▽ ̄)ブ。


Step 1

首先要看出来这是一个计数题对吧。。。

计数题有很多做法,对于这个题,我们考虑合理枚举,即不重复不遗漏地枚举所有情况,然后乘上一个组合数,并通过前缀和优化来降低复杂度。


Step 2

枚举什么东西呢?

我们考虑重新定义一下题目中的\(s\)和\(t\)。

我们定义\(t\)为,第一次取的蓝色球的位置,同时,为了构造出尽量多的方案,这个\(t\)要尽量地靠左。

举个栗子吧,比如我们想第一个取蓝色球,那么就有\(t = a + 1\),如果我们想等所有的红色球取完再取蓝色球,那么\(t = 1\)。

这里说的不太清楚。。。大家意会一下QAQ

于是我们首先枚举\(t\),即第一个取的蓝色球的位置,那么我们在取到这个球之前,首先需要从首部取\(a + 1 - t\)个红色球。

也就是说,我们得到的结果序列,是以\(a + 1 - t\)个红色球和一个蓝色球开始的,对于不同的\(t\),我们得到的序列肯定是不同的,不会重复。

同时,因为我们肯定要取蓝色球,所以也覆盖了所有情况而不会遗漏。


Step 3

确定了一个\(t\)之后,我们取走最前面的\(a + 1 - t\)个红色球和在\(t\)位置的一个蓝色球。剩余\(t - 1\)个红色球和\(b - 1\)个蓝色球。

接下来该枚举什么?

考虑现在一共有\(t + b - 2\)个球,我们取走\(b - 1\)个,使得剩下\(t - 1\)个球,然后\(t\)这个位置就没有用了,接下来就可以考虑确定\(s\)的位置。

于是我们枚举\(i\),即剩下的\(t - 1\)个球中,蓝色球的数量。

然后,确定了\(i\)之后,我们发现我们需要取走\(i\)个红色球和\(b - 1 - i\)个蓝色球。

容易发现,接下来准备取走的球,是不受位置限制的,颜色可以任意取,也就是说,这即将要取走的\(b - 1\)个球中,红色球和蓝色球可以排在任意位置。

于是,取走这\(b - 1\)个球的方案数就是\(C_{b-1}^{i}\)。

同样,当我们固定了\(t\)之后再枚举\(i\),也肯定是不重复不遗漏的,原因太显然了我就懒得讲了大家自己体会叭。。。


Step 4

现在我们剩了\(t - 1 - i\)个红色球和\(i\)个蓝色球。

现在\(t\)这个位置已经没法用了,我们还想要取蓝色球的话,需要新建一个位置\(s\),于是我们枚举\(s\)的位置。

注意,因为现在红色球只有\(t - 1 - i\)个,所以\(s\)最多枚举到\(t - i\)。

同理,确定了一个\(s\)之后,我们需要先取走\(t - i - s\)个红色球,然后再取走一个蓝色球,和上面的情况类似,这里也是不重复不遗漏的。


Step 5

现在我们只剩\(s - 1\)个红色球和\(i - 1\)个蓝色球了。

类似Step 3,我们考虑取走\(i - 1\)个球,剩余\(s - 1\)个球,枚举这剩余\(s - 1\)个球中,蓝色球的数量\(j\),那么我们要取走\(j\)个红色球和\(i - 1 - j\)个蓝色球。

同理,取这些球的时候是不受位置限制的,方案数是\(C_{i-1}^{j}\)。


Step 6

于是我们就只剩最后\(s - 1\)个球了,只能从首部一个一个取。


Step 7

我们枚举了\(t, i, s, j\)四个量,算法的时间复杂度为\(O(n^4)\)。

然后我们发现,枚举\(j\)并累加\(C_{i-1}^{j}\),实际上是杨辉三角第\(i-1\)行的一个前缀和,于是可以记\(sum[i][j]\)为杨辉三角第\(i\)行前\(j\)项的和,复杂度变为\(O(n^3)\)。

我们还能发现,枚举\(s\)并累加\(sum[i-1][min(s-1,i-1)]\),其实也是\(sum[i-1]\)的一个前缀和,于是记\(f[i][j]\)为\(sum[i]\)的前\(j\)项的和。

于是复杂度就变成了\(O(n^2)\)辣~

撒花花~★,°:.☆( ̄▽ ̄)/$:.°★

(我想了一整个下午加一整个晚上好叭QAQ)


Code

代码如下

#include <cstring>
#include <cstdio>
#include <algorithm> using namespace std;
typedef long long ll;
const int MAXN = 2010;
const int MOD = 1e9+7;
int _w; int C[MAXN][MAXN], sum[MAXN][MAXN], f[MAXN][MAXN];
void prelude() {
for( int i = 0; i < MAXN; ++i ) {
f[i][0] = sum[i][0] = C[i][0] = 1;
for( int j = 1; j <= i; ++j )
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
for( int j = 1; j < MAXN; ++j )
sum[i][j] = (sum[i][j-1] + C[i][j]) % MOD;
for( int j = 1; j < MAXN; ++j )
f[i][j] = (f[i][j-1] + sum[i][j]) % MOD;
}
} int solvet( int t, int b ) {
int ans = 1; // i == 0
for( int i = 1; i <= min(t-1, b); ++i )
ans = int((ans + (ll)f[i-1][t-i-1] * C[b][i]) % MOD);
return ans;
} int main() {
prelude();
int a, b;
_w = scanf( "%d%d", &a, &b );
if( !a || !b ) return puts("1"), 0;
int ans = 0;
for( int t = 1; t <= a+1; ++t )
ans = (ans + solvet(t, b-1)) % MOD;
printf( "%d\n", ans );
return 0;
}

【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数的更多相关文章

  1. Atcoder CODE FESTIVAL 2017 qual B E - Popping Balls 组合计数

    题目链接 题意 \(A+B\)个球排成一行,左边\(A\)个为红球,右边\(B\)个为蓝球. 最开始可以选择两个数\(s,t\),每次操作可以取左起第\(1\)或\(s\)或\(t\)个球.问有多少种 ...

  2. 题解【AtCoder - CODE FESTIVAL 2017 qual B - D - 101 to 010】

    题目:https://atcoder.jp/contests/code-festival-2017-qualb/tasks/code_festival_2017_qualb_d 题意:给一个 01 串 ...

  3. Atcoder Code Festival 2017 qual C 10.22 D题题解

    [题意概述] 给出一个只有小写字母的序列,问最少把序列分成几段可以满足每一段可以通过变换成为回文串.变换指的是交换子序列中的字母的位置. [题解] 我们把a~z分别设为2^0~2^25,每个子序列满足 ...

  4. Atcoder CODE FESTIVAL 2017 qual B D - 101 to 010 dp

    题目链接 题意 对于一个\(01\)串,如果其中存在子串\(101\),则可以将它变成\(010\). 问最多能进行多少次这样的操作. 思路 官方题解 转化 倒过来考虑. 考虑,最终得到的串中的\(' ...

  5. Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分

    题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...

  6. Atcoder CODE FESTIVAL 2017 qual B C - 3 Steps 二分图

    题目链接 题意 给定一个无向图,\(n\)个点,\(m\)条边(\(n,m\leq 1e5\)). 重复如下操作: 选择相异的两点u,v满足从点u出发走三条边恰好能到达点v.在这样的u,v点对之间添一 ...

  7. atcoder/CODE FESTIVAL 2017 qual B/B(dfs染色判断是否为二分图)

    题目链接:http://code-festival-2017-qualb.contest.atcoder.jp/tasks/code_festival_2017_qualb_c 题意:给出一个含 n ...

  8. Atcoder CODE FESTIVAL 2017 qual C C - Inserting 'x' 回文串

    题目链接 题意 给定字符串\(s\),可以在其中任意位置插入字符\(x\). 问能否得到一个回文串,若能,需插入多少个\(x\). 思路 首先统计出现次数为奇数的字符\(cnt\). \(cnt\ge ...

  9. 101 to 010 Atcoder CODE FESTIVAL 2017 qual B D

    https://www.luogu.org/problemnew/show/AT3575 题解 根本不会.. 错误记录:缺少32行的转移.显然这个转移是必要的 #include<cstdio&g ...

随机推荐

  1. Docker入门与实践之 docker安装与了解

    一.Docker 概述 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后 ...

  2. Karen and Coffee CF 816B(前缀和)

    Description To stay woke and attentive(专注的) during classes, Karen needs some coffee! Karen, a coffee ...

  3. Alpha发布用户使用报告

    此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2325] 组名:可以低头,但没必要 组长:付佳 组员:张俊余 李文涛 孙 ...

  4. SQL连接的方法

    1.创建连接字符串 string con = "Data Source=127.0.0.1;Initial Catalog=dingdan;Integrated Security=True& ...

  5. 团队Alpha冲刺(三)

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:家伟 组员8:政演 组员9:鸿杰 组员10:刘一好 组员11:何宇恒 展示组内最 ...

  6. Beta版冲刺前准备

    [团队概要] 团队项目名:小葵日记 团队名:日不落战队 队员及角色: 队员 角色 备注 安琪 前端工程师 队长 佳莹 前端工程师 智慧 后端工程师 章鹏 后端工程师 语恳 UI设计师 炜坤 前端工程师 ...

  7. ASP.NET MVC 4 内容映射

    文章:ASP.NET MVC 4 内容映射 地址:https://msdn.microsoft.com/zh-cn/library/gg416514(v=vs.108).aspx 模型-视图-控制器 ...

  8. java使用匿名类直接new接口

    翻看Vector代码的时候,看到这么一段. /** * Returns an enumeration of the components of this vector. The * returned ...

  9. TCP系列49—拥塞控制—12、DSACK下的拥塞撤销

    一.概述 DSACK下的虚假重传的检测我们之前重传部分的文章已经介绍过了,这里简单说一下拥塞控制部分的实现. linux内部会维护一个undo_retrans状态变量,其值为已经重传的次数减掉被DSA ...

  10. 搜索引擎Elasticsearch REST API学习

    Elasticsearch为开发者提供了一套基于Http协议的Restful接口,只需要构造rest请求并解析请求返回的json即可实现访问Elasticsearch服务器.Elasticsearch ...