传送门:题目
题意:
题目不难理解,就是给你一个序列,然后让你找到三个数相乘的最小值,问这有多少种组合情况。明显一道考组合数的题
题解:
思路不难想,但是坑点比较多。
我们先sort排序,然后计算出,最小的有多少个,次小的有多少个,次次小的有多少个。
坑点一,有四种情况:
情况一:最小的个数
min1≥
m
i
n
1
≥
3,那么ans=
C3min1
C
m
i
n
1
3
情况二:最小的个数
min1=2
m
i
n
1
=
2
,那么
ans=min2
a
n
s
=
m
i
n
2
(次小的个数)
情况三:最小的个数
min1=1
m
i
n
1
=
1
,次小的个数
min2≥2
m
i
n
2
≥
2
,那么ans=
C2min2
C
m
i
n
2
2
情况四:最小的个数
min1=1
m
i
n
1
=
1
,次小的个数
min2=1
m
i
n
2
=
1
,那么
ans=min3
a
n
s
=
m
i
n
3
(次次小的个数)
坑点二:组合数的计算不能套通式,就是阶乘的那个,写题的时候,傻乎乎的我直接套了个阶乘函数,没看到n的范围是 105 10 5 , 105! 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;
}