zoukankan      html  css  js  c++  java
  • 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数

    蒟蒻__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
    ", ans );
    	return 0;
    }
    
  • 相关阅读:
    virtualenv的使用
    node.js报错:Cannot find module 'xxx'的解决办法
    mysql
    cProfile分析程序性能
    python实现一个无序单链表
    修改pycharm中的flask项目名遇到的坑
    Model class apps.goods.models.GoodsType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS
    已安装的nginx添加其他模块
    pip install 一个本地包时提示error: Microsoft Visual C++ 14.0 is required.
    解决adober reader已停止工作的问题
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/7695949.html
Copyright © 2011-2022 走看看