训练赛上一题,当时没做出来,Orz太弱了
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input
6 -45 22 42 -16 -41 -27 56 30 -36 53 -37 77 -36 30 -75 -46 26 -38 -10 62 -32 -54 -6 45
Sample Output
5
Hint
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
题意:给出4个数列,从每个数列中选取一个元素,有多少种组合使得和为0?
思路:首先如果直接for暴力O(n^4)肯定时不行的,然后我们能想到如果让 c[i]和d[i]合并 a[i]与b[i]合并 找他们的相反数有多少个就可以了,
这里便出现了二分的应用:求 一个数 在一段序列中出现的次数。
我们可以先用 lower_bound 查找第一个大于x的数
函数lower_bound()在first和last中进行二分查找,如一个数组number序列1,2,2,4.lower_bound(2)后,返回的位置是1(下标)也就是2所在的位置,(只在单调递增的数组中适用)
函数upper_bound()返回的在前闭后开区间查找的关键字的上界,如一个数组number序列1,2,2,4.upper_bound(2)后,返回的位置是3(下标)也就是4所在的位置,
代码:
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <string> #include <cmath> #include <vector> #include <stack> #include <queue> #include <stack> #include <list> #include <map> #include <set> //#include <unordered_map> #define Fbo friend bool operator < (node a, node b) #define mem(a, b) memset(a, b, sizeof(a)) #define FOR(a, b, c) for(int a = b; a <= c; a++) #define RFOR(a,b, c) for(int a = b; a >= c; a--) #define sc(a) scanf("%d",&a) #define off ios::sync_with_stdio(0) bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; } using namespace std; typedef pair<int, int> pii; typedef long long ll; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int Maxn = 5050; const double pi = acos(-1.0); const double eps = 1e-8; int a[Maxn], b[Maxn], c[Maxn], d[Maxn]; int f[Maxn*Maxn], k=0; int main() { int n; sc(n); FOR(i,1,n) { sc(a[i]), sc(b[i]), sc(c[i]), sc(d[i]); } FOR(i, 1, n) { FOR(j, 1, n) { f[k++] = c[i] + d[j]; } } sort(f, f + k); ll ans = 0; FOR(i, 1, n) { FOR(j, 1, n) { ll t = -(a[i] + b[j]); //二分搜索取出cd中和为t的部分有多少个 ans += upper_bound(f, f + n * n, t) - lower_bound(f, f + n * n, t); } } printf("%lld\n", ans); }
来源:https://www.cnblogs.com/AlexLINS/p/12643608.html