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?
 

 

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];
struct node
{
  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 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 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;
}
 
 
夹逼法:
#include<stdio.h>
#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);
//unique作用去除相邻的重复元素,如果想把一个列表中的元素全部删除,那么就要先将其排序
  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;
}
 
set的应用:
#include<stdio.h>
#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"
int n;
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 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;
}