ACM2021辽宁省赛:E-生活大爆炸

579 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

E-生活大爆炸

题目描述

有n个男孩和m个女孩参加戏剧俱乐部。要制作一部戏剧《生活大爆炸》,他们需要选择一组由t个演员组成的剧组,其中包括不少于4名男孩和不少于1名女孩。有多少种方法可以组成一个小组?当然,只有剧团组成不同的变体才被认为是不同的。

输入描述:

一行包含三个整数n,m,t (4≤n≤30, 1≤m≤30, 5≤t≤n+m)

输出描述:

一行表示答案。

示例1

输入

5 2 5

输出

10

问题解析

这道题主要思路就是我们高中就学过的组合数计算。

男生有n人,女生有m人,需要组成总人数为t的队伍,其中男生人数不能少于4人,女生人数不能少于1人。

那么可能的排列组合就是:4个男生和t-4名女生,5个男生和t-5名女生,……,t-1名男生和1名女生。

对于第一个组合来说,就是n个男生中随机选出4个,搭配上m个女生中随机选出t-4个,即:C(n,4)*C(m,t-4)。其余的以此类推,把所有的组合数相加即可。

注意点1:由于结果可能很大,数据类型用int显然是不行的,这里要采用long long。

注意点2:有的同学算组合数C(a,b)时,是先计算a *(a-1) *(a-2) *…… *(1),再计算1 *2 *3 *…… *b,最后用两个结果相除。但是要注意,a最大可到30,如果傻傻的从1乘到30,哪怕是longlong也无法承受。(提问:longlong的范围是多少呢?不要求记住具体数,记住他是2的几次幂即可)。

这里我们涉及到组合数的递推公式:

屏幕截图 2022-10-08 151650.png

也就是说,只要我们知道了C(n-1,m)和C(n-1,m-1),我们将他们相加便可以得到C(n,m)。以此类推。

为了方便,我们可以开一个二维数组C,将C(n,m)的结果存在C[n] [m]中,这样后续计算其它组合数时我们就省去了重复的计算,需要什么可以直接从数组中获取。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>

#pragma GCC optimize(2)
#pragma GCC optimize(3)

#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 4e5 + 50;

int C[70][70];
void init()
{
    for (int i = 0; i <= 70; i++)
        for (int j = 0; j <= i; j++) {
            if (!j)
                C[i][j] = 1;
            else
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
        }
}

void solve()
{
    int n, m, t;
    cin >> n >> m >> t;
    init();
    int res = 0;
    for (int i = 4; i <= min(n, t - 1); i++)
    {
        res += C[n][i] * C[m][t - i];
    }
    cout << res;
}

signed main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;

    while (t--)
    {
        solve();
    }
    return 0;
}