HDU - 2141 Can you find it?
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.
Input
There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.
Output
For each case, firstly you have to print the case number as the form “Case d:”, then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print “YES”, otherwise print “NO”.
Sample Input
3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10
Sample Output
Case 1:
NO
YES
NO
问题求A+B+C=X是否存在
暴力求解求出三个数组所有值的可能然后从中查找是否有该值是不可行的,其时间复杂度为O(N^3)。
可以将等式进行变换为A+B=X-C,这样需要在A+B所有的可能值中查找X-C是否存在,将时间复杂度降为O(N^2),同时查找我们使用二分查找更快速。
#include<iostream>
#include<algorithm>
using namespace std;
int a[501], b[501],c[501],box[250005], s; //box注意开大,避免数组内存不够
int l, n, m, k;
int binary_search(int x) //在box中二分查找x
{
int left = 1, right = k;
while (left <= right)
{
int mid = (left + right) / 2;
if (x > box[mid])
left = mid + 1;
else if (x < box[mid])
right = mid - 1;
else
return 1;
}
return 0;
}
int main()
{
int cases = 0;
while (scanf("%d%d%d", &l, &n, &m) != EOF)
{
cases++;
for (int i = 1; i <= l; i++)
cin >> a[i];
for (int i = 1; i <= l; i++)
cin >> b[i];
k = 0;
for (int i = 1; i <= l; i++) //计算两组数和的所有可能并排序
{
for (int j = 1; j <= n; j++)
{
box[++k] = a[i] + b[j];
}
}
sort(box + 1, box + k+1);
for (int i = 1; i <= l; i++)
cin >> c[i];
cin >> s;
cout << "Case " << cases << ':' << endl;
while (s--)
{
int x;
cin >> x;
int flag = 0;
for (int i = 1; i <= m; i++)
{
if (binary_search(x - c[i]))
{
flag = 1;
break;
}
}
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
return 0;
}
POJ2785 4 Values whose Sum is 0
Time Limit: 15000MS | Memory Limit: 228000K | |
Total Submissions: 29423 | Accepted: 8951 | |
Case Time Limit: 5000MS |
Description
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 228 ) 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).
暴力枚举明显是不可能的,可以转化为A+B=-(C+D),将A+B所有值放入一个数组中然后从数组中二分查找-(C+D)。
所求所有可能的总数,故需要计算-(C+D)在数组中是否存在,存在则有几个,就用到了STL中的上下界二分查找。
#include<iostream>
#include<algorithm>
using namespace std;
int a[4001], b[4001], c[4001], d[4001], box1[16000000], box2[16000000];
int n, k1 = 0, k2 = 0, ans = 0; //box1中存放A+B,box2中存放C+D
int main()
{
while (scanf("%d", &n) != EOF)
{
k1 = 0, k2 = 0, ans = 0;
for (int i = 1; i <= n; i++)
scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
box1[++k1] = a[i] + b[j];
sort(box1 + 1, box1 + k1 + 1); //在box1中二分查找,从小到大排序
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
box2[++k2] = c[i] + d[j];
for (int i = 1; i <= k2; i++)
{
int x1 = lower_bound(box1 + 1, box1 + k1+1, -box2[i]) - box1;//下界的角标序号
int x2 = upper_bound(box1 + 1, box1 + k1+1, -box2[i]) - box1; //上界的角标序号
if (x1 != x2) //序号不相同则至少存在一个
ans += (x2 - x1);
}
cout << ans << endl;
}
return 0;
}