CTU Open Contest 2019 A. Beer Barrels 组合数

A. Beer Barrels 组合数

比赛地址:

https://www.jisuanke.com/contest/7321?view=challenges

题意:

给你四个数A,B,K,C,求由A,B组成的K位数中,C出现的次数是多少。

基本思路:

我们想如果A,B相同且等于C那么显然答案是K,如果A,B,C都不相等那么答案显然是0,我们只要考虑当A,B中的一个等于C的情况,假设A=C那么这时候我们知道在K位中出现 1 个 A 的方案数为 C(K,1) 出现 2 个 A 的方案为 C(K,2) 那么在出现 i 个A的方案中出现A的总次数即 i * C(K,i),所以答案为C(K,1)*1+C(K,2)*2+C(K,3)*3+…+C(K,K)*K。

注意求组合数的模板,还有取模一定要记得 先 + MOD 再 % MOD

#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define int long long
#define INF 0x3f3f3f3f

const int maxn = 1010;
int fact[maxn];
inline int extgcd(int a,int b,int &x,int &y) {
    int d = a;
    if (b != 0) {
        d = extgcd(b, a % b, y, x);
        y -= (a / b) * x;
    } else {
        x = 1;
        y = 0;
    }
    return d;
}
inline int mod_inverse(int a,int m){
    int x,y;
    extgcd(a,m,x,y);
    return (m + x % m) % m;
}
inline int mod_fact(int n,int p,int &e) {
    e = 0;
    if (n == 0) return 1;
    int res = mod_fact(n / p, p, e);
    e += n / p;

    if (n / p % 2 != 0) return res * (p - fact[n % p] % p);
    return res * fact[n % p] % p;
}
inline int mod_comb(int n,int k,int p) {
    if (n < 0 || k < 0 || n < k) return 0;
    int e1, e2, e3;
    int a1 = mod_fact(n, p, e1), a2 = mod_fact(k, p, e2), a3 = mod_fact(n - k, p, e3);
    if (e1 > e2 + e3) return 0;
    return a1 * mod_inverse(a2 * a3 % p, p) % p;
}
int A,B,K,C;
const int mod = 1e9 + 7;
signed main() {
    IO;
    cin >> A >> B >> K >> C;
    fact[0] = 0, fact[1] = 1;
    for (int i = 2; i <= maxn; i++) fact[i] = fact[i - 1] * i % mod;
    if (A != C && B != C) {
        cout << 0 << endl;
    } else {
        if (A == B) cout << K << endl;
        else {
            int ans = 0;
            for (int i = 1; i <= K; i++) {
                ans = (ans + i * mod_comb(K, i, mod) + mod) % mod;
            }
            cout << ans << endl;
        }
    }
    return 0;
}
发布了23 篇原创文章 · 获赞 7 · 访问量 1750

猜你喜欢

转载自blog.csdn.net/weixin_44164153/article/details/104458432