训练赛上一题,当时没做出来,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