【思维题】CodeForce 817B Makes And The Product

    xiaoxiao2025-06-10  54

    这段时间要沉迷刷题一段时间了,就让陪我一起吧!

    一、题目大意

    现在发现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; }

    如果有问题,欢迎大家指正!!!

    最新回复(0)