CodeForce-817B 模拟 组合数

传送门:题目

题意:

题目不难理解,就是给你一个序列,然后让你找到三个数相乘的最小值,问这有多少种组合情况。明显一道考组合数的题

题解:

思路不难想,但是坑点比较多。
我们先sort排序,然后计算出,最小的有多少个,次小的有多少个,次次小的有多少个。
坑点一,有四种情况:
情况一:最小的个数 m i n 1 3,那么ans= C m i n 1 3
情况二:最小的个数 m i n 1 = 2 ,那么 a n s = m i n 2 (次小的个数)
情况三:最小的个数 m i n 1 = 1 ,次小的个数 m i n 2 2 ,那么ans= C m i n 2 2
情况四:最小的个数 m i n 1 = 1 ,次小的个数 m i n 2 = 1 ,那么 a n s = m i n 3 (次次小的个数)

坑点二:组合数的计算不能套通式,就是阶乘的那个,写题的时候,傻乎乎的我直接套了个阶乘函数,没看到n的范围是 10 5 10 5 ! 直接爆RE

坑点三:结果要开long long,上面再计算组合数的时候,会爆int

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int a[maxn];

int main(void) {
    int n, i, j, k,min1 = 1, min2 = 1, min3 = 1;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    sort(a, a + n);
    for (i = 1; i < n; i++) {
        if (a[i] == a[i - 1])
            min1++;
        else
            break;
    }
    for (j = i + 1; j < n; j++) {
        if (a[j] == a[j - 1])
            min2++;
        else
            break;
    }
    for (k = j + 1; k < n; k++) {
        if (a[k] == a[k - 1])
            min3++;
        else
            break;
    }

    long long ans ;
    if (min1 >= 3)
        ans = min1 * (min1 - 1LL) * (min1 - 2LL) / 6;
    else if (min1 + min2 >= 3) {
        if (min1 == 2)
            ans = min2;
        else
            ans = min2 * (min2 - 1LL) / 2;
    }
    else
        ans = min3;
    printf("%I64d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shadandeajian/article/details/81588448