这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
现在发现codeforce的好处了,就是题目都比较简洁。这道题的大致意思是给你一个长度为N的数组a,然后让你找有多少个元组(i, j, k),使得a[i]*a[j]*a[k]最小。
二、题目思路以及AC代码
题目的意思很简单,我一开始想到的思路是桶排,毕竟这个叙述以及思路都太适合桶排了,当然桶排也确实可以很方便的解决这个问题,如果忽略这个题的数据范围。(哭)
这题给出的数组元素是1≤x≤1e9,桶排的话就需要4G的存储空间,肯定不行,所以就得另寻他法,然后我就想到,因为数组元素是正整数的,所以直接找最小的三个元素相乘肯定是最小的,但要考虑会有重复元素。
虽然有重复元素,但我们还是可以首先找到数组中数最小的三个元素,并且记录其在数组里出现的次数,然后最小值的出现次数大于3,假设为k,那么我们的结果就是在k个元素中选择3个,也就是组合数。如果最小值出现的次数是2,那么我们的结果就是在次小值出现的次数中选择1个;同理,如果最小值出现的次数是1,那么我们还得对次小值出现次数进行讨论,如果次小值出现次数大于等于2,那么结果就是在次小值出现次数中选择2个,而如果次小值出现次数等于1,那么我们的结果就是在第三小值的出现次数中选1个。
有了以上的分类讨论情况,接下来的代码也就很容易理解了。当然,这题有一个需要特别注意的点!也坑了我的,就是在算组合数的时候,由于给的N较大,所以会爆int,哎,我就是这么WA的。
下面给出AC代码:
#include <iostream>
#define INF 2147483647
using namespace std;
long long C[100005][4];
void get_C() {
C[0][0] = 1;
for (int i = 1; i <= 100000; i++) {
C[i][0] = 1;
for (int j = 1; j <= 3 && j <= i; j++) {
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
}
int main()
{
get_C();
int N;
cin >> N;
int min1 = INF, min2 = INF, min3 = INF;
int cnt1 = 0, cnt2 = 0, cnt3 = 0;
int num = 0;
for (int i = 0; i < N; i++) {
cin >> num;
if (num < min1) {
min3 = min2;
cnt3 = cnt2;
min2 = min1;
cnt2 = cnt1;
min1 = num;
cnt1 = 1;
}
else if (num == min1){
cnt1++;
}
else if (num < min2) {
min3 = min2;
cnt3 = cnt2;
min2 = num;
cnt2 = 1;
}
else if (num == min2) {
cnt2++;
}
else if (num < min3) {
min3 = num;
cnt3 = 1;
}
else if (num == min3) {
cnt3++;
}
}
long long res = 0;
if (cnt1 >= 3) {
res = C[cnt1][3];
}
else if (cnt1 == 2) {
res = C[cnt2][1];
}
else if (cnt2 >= 2) {
res = C[cnt2][2];
}
else {
res = C[cnt3][1];
}
cout << res << endl;
return 0;
}
如果有问题,欢迎大家指正!!!