4 Values whose Sum is 0
Time Limit: 15000MS | Memory Limit: 228000K | |
Total Submissions: 26489 | Accepted: 7976 | |
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 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).
Source
[Submit] [Go Back] [Status] [Discuss]
题意:给你四列数,问从这四列数中各选一个数使他们的和是0的情况有多少种?思路:二分找答案,先将前两列数分别加起来存到一个新的数组sum里,然后再遍历后两列的数的和,看从sum数组中是否能找到他们的相反数,如果有就让ans+1;
//直接利用二分函数 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #define inf 0x3fffffff using namespace std; typedef long long LL; const double eps=1e-8; const double pi=acos(-1); const int N=4e3+1; int n,a[N],b[N],c[N],d[N],s[N*N],tot; int finf(int x) { int l=lower_bound(s,s+tot,x)-s; int r=upper_bound(s,s+tot,x)-s; return r-l; } int main() { tot=0; int ans=0; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]); for(int i=0;i<n;i++) for(int j=0;j<n;j++) s[tot++]=a[i]+b[j]; sort(s,s+tot); for(int i=0;i<n;i++) for(int j=0;j<n;j++) ans+=finf(-(c[i]+d[j])); printf("%d\n",ans); }
//自己写二分查找 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #define inf 0x3fffffff using namespace std; typedef long long LL; const double eps=1e-8; const double pi=acos(-1); const int N=4e3+1; int n,a[N],b[N],c[N],d[N],s[N*N],tot; int finf(int x) { int ansl,ansr,mid; int l=0,r=tot; while(l<r) { mid=(l+r)/2; if(s[mid]>=x) r=mid; else l=mid+1; } ansl=l; l=0,r=tot; while(l<r) { mid=(l+r)/2; if(s[mid]>x) r=mid; else l=mid+1; } ansr=l; return ansr-ansl; } int main() { tot=0; int ans=0; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]); for(int i=0;i<n;i++) for(int j=0;j<n;j++) s[tot++]=a[i]+b[j]; sort(s,s+tot); for(int i=0;i<n;i++) for(int j=0;j<n;j++) ans+=finf(-(c[i]+d[j])); printf("%d\n",ans); }
那我们再接着来看一道一模一样的题:
Can you find it?
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/10000 K (Java/Others)Total Submission(s): 37412 Accepted Submission(s): 9145
Problem Description
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 31 2 31 2 31 2 331410
Sample Output
Case 1:NOYESNO
Author
wangye
Source
Recommend
威士忌
题意:给你三列数,然后n次查询,每次给出一个数,问是否能从那三列数中各选出一个使得他们的和等于这个数,如果能输出YES,否则NO。心路历程:是不是很简单啊,确实很简单啊,不是跟上面的一模一样的吗?这两道题分别出现在这三天的两场比赛中,中间只隔了一天,看到这题的时候内心很是激动,因为上一场刚刚出现过所以印象还是非常清晰的,代码也很快就写出来了,但是一交MLE????这种情况没遇到过几次,当时有点懵,然后算了一下空间复杂度,好像确实超了(我的新的sum数组里存的是三个数列的各种情况的和,要开n*n*n大小的数组,n<=500,题目内存只给了10000 kB,确实会超),然后我同样用map存三个数列的各种情况 的和还是MLE,当时认真想了一下,既然存三个数列的和的情况会MLE,那就存先两个数列的各种情况和呗,但我依旧用的是map来操作,so 结果依旧是MLE,这个时候就有点绝望了,这都不行,算了一下空间感觉够啊(不知道map里面的空间会占多少?),比赛的时候就是没有再用二分试一下存两个数列的各种情况的和,比赛刚结束我问旁边的伙伴,他说用二分存前两列的各种情况和我就恍然大悟,,,,,,,,,啊,又一次和AC擦肩而过,多么好的AC机会啊,多么痛的领悟啊!!!!!!!!!!!!以后比赛如果遇到这种情况,一定要把所有想到情况都是一遍,不要怕wa,不要怕罚时,反正已经罚时爆炸了,怕什么
接下来就直接看代码吧:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#define inf 0x3fffffff
using namespace std;
typedef long long LL;
const double eps=1e-8;
const double pi=acos(-1);
const int N=502;
int aa,bb,cc,tot;
LL a[N],b[N],c[N],sum[N*N];
int main()
{
int s,d,t=1,ans,flag;
while(~scanf("%d%d%d",&aa,&bb,&cc))
{
tot=flag=0;
for(int i=0;i<aa;i++)
scanf("%I64d",&a[i]);
for(int i=0;i<bb;i++)
scanf("%I64d",&b[i]);
for(int i=0;i<cc;i++)
scanf("%I64d",&c[i]);
for(int i=0;i<aa;i++)
for(int j=0;j<bb;j++)
sum[tot++]=a[i]+b[j];
sort(sum,sum+tot);
scanf("%d",&s);
printf("Case %d:\n",t++);
while(s--)
{
scanf("%d",&d);
flag=0;
for(int i=0;i<cc;i++)
{
ans=lower_bound(sum,sum+tot,d-c[i])-sum;
if(sum[ans]==d-c[i])
{
flag=1;
printf("YES\n");
break;
}
}
if(!flag) printf("NO\n");
}
}
}