题意
给定一个长度为 n n n的数组 a a a和一个正整数 k k k,从数组中选择四个数,要求四个数的乘积小于等于 k k k,求方案总数。
- 数组中可能出现多个值相同的数。
- 每次选择四个数时,同一个数不能被选择两次,而值相同的两个不同的数可以同时被选。
- 1 ≤ n ≤ 1 0 3 1 \leq n \leq 10^3 1≤n≤103
- 1 ≤ a [ i ] ≤ 1 0 6 ( 1 ≤ i ≤ n ) 1 \leq a[i] \leq 10^6 (1 \leq i \leq n) 1≤a[i]≤106(1≤i≤n)
- 1 ≤ k ≤ 1 0 6 1 \leq k \leq 10^6 1≤k≤106
分析
两个数或三个数的加和/乘积等于一个定值 k k k的方案数是一个非常经典的算法题,在竞赛和工作面试中非常常见。
这道题是我第一次接到出题任务时构思了两小时想出来的题目,其实拓展出这个问题并不难,主要时间花在了想出好的解法并充分验证其正确性。
题目上传到了Lintcode:题目链接
此处提供的参考解法是折半枚举和容斥定理。
首先有一个非常暴力但一定正确的算法是从数组中枚举四个数,判断其乘积是否小于等于 k k k,复杂度为 O ( n 4 ) O(n^4) O(n4)
现在考虑如何优化到 O ( n 2 ) O(n^2) O(n2)
维护两个数组 C n t Cnt Cnt, S u m Sum Sum
其中
C n t [ i ] Cnt[i]