其他分享
首页 > 其他分享> > AT3576 Popping Balls

AT3576 Popping Balls

作者:互联网

https://www.luogu.com.cn/problem/AT3576

又盯了半个多小时才看懂之前写的是啥

妙妙组合数学思维题啊啊

首先不管\(s,t\),要拿红球肯定是从\(1\)开始拿,不亏

假设要拿第一个蓝球了,那么我们可以把\(t\)设到当前蓝球第一个位置,不亏

假设\(t\)那个位置已经没有球了,但还是想要拿篮球,那把\(s\)设到现在蓝球的第一个位置,不亏

然后就可以考虑计算了

假设从\(t\)处拿了\(i\)个蓝球,那么要从\(1\)处拿\(B-i\)个蓝球,才能让\(t\)那个位置没有球,进入第三步

假设从\(s\)处拿了\(j\)个蓝球,那么要从\(1\)处拿走\(B-i-j\)个红球,才能让\(s\)处没有球

第一个是\(\large \binom{B-1}{i-1}\),因为第一个拿了肯定是蓝球,随意上下都要\(-1\),同理,第二个是\(\large \binom{B-i-1}{j-1}\)

还剩下\(A-(B-i)-(B-i-j)\)个红球,可以在\(s,t\)拿蓝球之前,第二步之后任意取,共\(3\)段,用插板法可得为

\(\large \binom{A-(B-i)-(B-i-j)-1}{3-1}\)

(剩下的蓝球只能从\(A\)处一个个取了)

因为上面那种只考虑的分成三段的情况,实际上可以蓝色整个作为一段,那样的方案数是\(A+1\)的,单独加上即可

code:


#include<bits/stdc++.h>
#define ll long long
#define N 4050
#define mod 1000000007
using namespace std;
int a, b, c[N][N];
int C(int n, int m) {
    if(m > n || n < 0 || m < 0) return 0;
    return c[n][m];
}
int main() {
    scanf("%d%d", &a, &b);
    for(int i = 0; i <= a + b; i ++) c[i][0] = 1;
    for(int i = 1; i <= a + b; i ++) 
        for(int j = 1; j <= i; j ++)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
    
    ll ans = a + 1;
    for(int i = 1; i <= b; i ++)
        for(int j = 1; j <= b - i; j ++)
            ans = (ans + 1ll * C(b - 1, i - 1) * C(b - 1 - i, j - 1) % mod * C(a - (b - i) - (b - i - j) + 2, 2) % mod) % mod;
    printf("%lld", ans);
    return 0;
}

标签:Balls,AT3576,int,不亏,large,蓝球,binom,Popping,define
来源: https://www.cnblogs.com/lahlah/p/15924724.html