Trouble
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2284 Accepted Submission(s): 726
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?
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
代码:
哈希链表法:
#include<stdio.h>
#include<string.h>
#define MOD 100005
typedef __int64 LL;
LL a[6][205];
int head[MOD];
#include<string.h>
#define MOD 100005
typedef __int64 LL;
LL a[6][205];
int head[MOD];
struct node
{
LL date; //存储数值;
int next; //标记同余的前一位的位置;
}node[40100];
int t,n,cnt ;//cnt标记结点个数;
{
LL date; //存储数值;
int next; //标记同余的前一位的位置;
}node[40100];
int t,n,cnt ;//cnt标记结点个数;
void insert(LL key)//插入;
{
int p;
if(key>0)
p=key%MOD;
else
p=(-key)%MOD;
int flag=0;
for(int i=head[p];i!=-1;i=node[i].next)
{
LL u=node[i].date;
if(u==key)
return ;
}
if(!flag)
{
node[cnt].date=key;
node[cnt].next=head[p];
head[p]=cnt++;
}
}
{
int p;
if(key>0)
p=key%MOD;
else
p=(-key)%MOD;
int flag=0;
for(int i=head[p];i!=-1;i=node[i].next)
{
LL u=node[i].date;
if(u==key)
return ;
}
if(!flag)
{
node[cnt].date=key;
node[cnt].next=head[p];
head[p]=cnt++;
}
}
int find(LL key)//查询;
{
int p;
if(key>0)
p=key%MOD;
else
p=(-key)%MOD;
for(int i=head[p];i!=-1;i=node[i].next)
{
LL u=node[i].date;
if(u==key)
return 1;
}
return 0;
}
{
int p;
if(key>0)
p=key%MOD;
else
p=(-key)%MOD;
for(int i=head[p];i!=-1;i=node[i].next)
{
LL u=node[i].date;
if(u==key)
return 1;
}
return 0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(head,0xff,sizeof(head)); //0xff表示-1;
for(int i=1;i<=5;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%I64d",&a[i][j]);
}
}
cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<+n;j++)
insert(a[1][i]+a[2][j]);
int flag=0;
for(int i=1;i<=n&&!flag;i++)
{
for(int j=1;j<=n&&!flag;j++)
{
for(int k=1;k<=n;k++)
{
if(find(-(a[3][i]+a[4][j]+a[5][k])))
{
flag=1;
break;
}
}
}
}
printf(flag?"Yes\n":"No\n");
}
return 0;
}
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(head,0xff,sizeof(head)); //0xff表示-1;
for(int i=1;i<=5;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%I64d",&a[i][j]);
}
}
cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<+n;j++)
insert(a[1][i]+a[2][j]);
int flag=0;
for(int i=1;i<=n&&!flag;i++)
{
for(int j=1;j<=n&&!flag;j++)
{
for(int k=1;k<=n;k++)
{
if(find(-(a[3][i]+a[4][j]+a[5][k])))
{
flag=1;
break;
}
}
}
}
printf(flag?"Yes\n":"No\n");
}
return 0;
}
夹逼法:
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long LL;
#define N 205
#include<algorithm>
using namespace std;
typedef long long LL;
#define N 205
LL a[6][N],M1[N*N],M2[N*N];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 1; i <= 5; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%I64d",&a[i][j]);
}
}
int len1=0,len2=0;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
M1[len1++] = a[1][i]+a[2][j];
M2[len2++] = a[3][i]+a[4][j];
}
}
sort(M1,M1+len1);
sort(M2,M2+len2);
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 1; i <= 5; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%I64d",&a[i][j]);
}
}
int len1=0,len2=0;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
M1[len1++] = a[1][i]+a[2][j];
M2[len2++] = a[3][i]+a[4][j];
}
}
sort(M1,M1+len1);
sort(M2,M2+len2);
//unique作用去除相邻的重复元素,如果想把一个列表中的元素全部删除,那么就要先将其排序
len1 = unique(M1,M1+len1)-M1;
len1 = unique(M1,M1+len1)-M1;
len2 = unique(M2,M2+len2)-M2;
int flag = 0;
for(int i = 1; i <= n && !flag ; i++)//夹逼
{
int l=0,r=len2-1;
LL k=-a[5][i];
while(l < len1 && r >= 0)
{
LL temp = M1[l]+M2[r];
if( temp < k )
l++;
else if(temp>k)
r--;
else
{
flag=1;
break;
}
}
}
puts( flag? "Yes" : "No");
}
return 0;
}
int flag = 0;
for(int i = 1; i <= n && !flag ; i++)//夹逼
{
int l=0,r=len2-1;
LL k=-a[5][i];
while(l < len1 && r >= 0)
{
LL temp = M1[l]+M2[r];
if( temp < k )
l++;
else if(temp>k)
r--;
else
{
flag=1;
break;
}
}
}
puts( flag? "Yes" : "No");
}
return 0;
}
set的应用:
#include<stdio.h>
#include<set> //set(集合)——包含了经过排序了的数据,这些数据的值(value)必须是唯一的。
using namespace std;
#include<set> //set(集合)——包含了经过排序了的数据,这些数据的值(value)必须是唯一的。
using namespace std;
#define REPI(it,c) for(set<LL>::iterator it=c.begin();it!=c.end();it++)
#define N 205
typedef __int64 LL;//要用typedef;
#define LLF "%I64d"
#define N 205
typedef __int64 LL;//要用typedef;
#define LLF "%I64d"
int n;
set<LL> sl,s2;
LL list[N];
LL list1[N*N],list2[N*N];
int p,p1,p2;
set<LL> sl,s2;
LL list[N];
LL list1[N*N],list2[N*N];
int p,p1,p2;
void init(
LL list[],int &p)
{
int i, j;
sl.clear();
for(i = 0;i < n;i ++)
{
LL tmp;
scanf(LLF,&tmp);
sl.insert(tmp);
}
s2.clear();
for(i = 0;i < n; i++)
{
LL tmp;
scanf(LLF, &tmp);
REPI(it, sl)
s2.insert(*it+tmp);
}
p = 0;
REPI(it,s2)
list[p++]=*it;
}
{
int i, j;
sl.clear();
for(i = 0;i < n;i ++)
{
LL tmp;
scanf(LLF,&tmp);
sl.insert(tmp);
}
s2.clear();
for(i = 0;i < n; i++)
{
LL tmp;
scanf(LLF, &tmp);
REPI(it, sl)
s2.insert(*it+tmp);
}
p = 0;
REPI(it,s2)
list[p++]=*it;
}
int main()
{
int i, j, T;
scanf("%d",&T);
while (T--)
{
scanf("%d", &n);
init( list1, p1);
init( list2, p2);
for(i = 0, p = 0; i < n; i++)
{
LL tmp;
scanf(LLF,&tmp);
list[p++]=tmp;
}
for ( i = 0; i < p; i++) //夹逼法;
{
int l = 0, r = p2 - 1;
LL flag = - list[i];
while (l < p1 && r >= 0)
{
LL tmp=list1[l]+list2[r];
if(tmp<flag)
l++;
else if(tmp>flag)
r--;
else
{
printf("Yes\n");
goto loop;
}
}
}
printf("No\n");
loop:;
}
return 0;
}