Trouble
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5752 Accepted Submission(s): 1594
Problem Description
Hassan is in trouble. His mathematics teacher has given him a very difficult problem called 5-sum. Please help him.
The 5-sum problem is defined as follows: Given 5 sets S_1,…,S_5 of n integer numbers each, is there a_1 in S_1,…,a_5 in S_5 such that a_1+…+a_5=0?
Input
First line of input contains a single integer N (1≤N≤50). N test-cases follow. First line of each test-case contains a single integer n (1<=n<=200). 5 lines follow each containing n integer numbers in range [-10^15, 1 0^15]. I-th line denotes set S_i for 1<=i<=5.
Output
For each test-case output “Yes” (without quotes) if there are a_1 in S_1,…,a_5 in S_5 such that a_1+…+a_5=0, otherwise output “No”.
Sample Input
2
2
1 -1
1 -1
1 -1
1 -1
1 -1
3
1 2 3
-1 -2 -3
4 5 6
-1 3 2
-4 -10 -1
Sample Output
No
Yes
尝试用二分把前三个数组求和的话超内存了,换了一种思路。5个数组将4组求和化成2组,这样就有3个数组了,不会超内存,在小的数组中枚举数,用游标法在另外两个和数组中查找是否有对应值使和为0.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAX=200+2;
ll s1[MAX]={0};
ll s2[MAX]={0};
ll s3[MAX]={0};
ll s4[MAX]={0};
ll s5[MAX]={0};
ll s12[MAX*MAX]={0};
ll s45[MAX*MAX]={0};
bool cmp(ll a,ll b)
{
return a<b;
}
int main()
{
int T;
int n;
cin>>T;
while(T--)
{
cin>>n;
for (int i=0;i<n;i++) cin>>s1[i];
for (int i=0;i<n;i++) cin>>s2[i];
for (int i=0;i<n;i++) cin>>s3[i];
for (int i=0;i<n;i++) cin>>s4[i];
for (int i=0;i<n;i++) cin>>s5[i];
int cnt1=0;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
s12[cnt1++]=s1[i]+s2[j];
int cnt2=0;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
s45[cnt2++]=s4[i]+s5[j];
sort(s12,s12+cnt1,cmp);
sort(s45,s45+cnt2,cmp);
bool find=false;
for (int i=0;i<n;i++)
{
int a=0;int b=cnt2-1;
while (true)
{
if (s12[a]+s45[b]==-s3[i])
{
find=true;
break;
}
else if (s12[a]+s45[b]>-s3[i])
{
b--;
if (b<0) break;
}
else
{
a++;
if (a>=cnt1) break;
}
}
if (find)
break;
}
if (find) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
哈希做法
#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<stack>
#include<set>
#include<map>
using namespace std;
const int MAX = 733733;
typedef long long ll;
int T, N;
ll A[5][205];
ll F[MAX];
bool used[MAX];
int Hash(ll x)
{
int p = x%MAX;
if (p < 0) p += MAX;
while (used[p] && F[p] != x)
p = (p + 1) % MAX;
return p;
}
int main()
{
cin.sync_with_stdio(false);
cin >> T;
while (T--)
{
memset(used,0,sizeof(used));
cin >> N;
for (int i = 0; i < 5; i++)
for (int j = 0; j < N; j++)
cin >> A[i][j];
for (int i=0;i<N;i++)
for (int j = 0; j < N; j++)
{
ll sum = -(A[0][i] + A[1][j]);
int pos = Hash(sum);
F[pos] = sum;
used[pos] = true;
}
bool Find = false;
for (int i=0;i<N;i++)
for (int j=0;j<N;j++)
for (int k = 0; k < N; k++)
{
ll sum = (A[2][i] + A[3][j] + A[4][k]);
int pos = Hash(sum);
if (used[pos])
{
Find = true;
i = N, j = N, k = N;
}
}
if (Find) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}