HDU

来源:互联网 发布:js如何隐藏div 编辑:程序博客网 时间:2024/06/06 03:04

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
221 -11 -11 -11 -11 -131 2 3-1 -2 -34 5 6-1 3 2-4 -10 -1
 

Sample Output
NoYes

发现哈希还挺有意思的,存大的数据非常好用,刚学的时候觉得哈希主要是用将数据离散化进行范围缩化,当时觉得改动了数据没关系,只要大小关系不变就好了

然后遇到了这道题,参考了大佬的哈希函数,琢磨了一阵子,感觉自己真菜鸡(一开始想着用STL的set来存,结果超时了,STL果然危险hhh)

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;long long num[5][205];int vis[401705];long long hashs[401705];int f(long long a)          //这里我看了好久,后来才想清楚{                           //不管是个啥值,首先得先弄成正数,这样vis数组才可以进行标记    int s=a%401705;    if(s<0)s+=401705;    while(vis[s]&&hashs[s]!=a)   //要是这个地方有标记了而且存储的那个值不是我现在这个值,那咱就换家店住        s=(s+1)%401705;    return s;                    //返回我存放值的那个地方}int main(){    int N,n;    long long t;    scanf("%d",&N);    while(N--)    {        bool label=false;        memset(vis,0,sizeof vis);        scanf("%d",&n);        for(int i=0;i<5;i++)           for(int j=0;j<n;j++)               scanf("%lld",&num[i][j]);        for(int i=0;i<n;i++)            for(int j=0;j<n;j++)            {                int temp=f(-(num[0][i]+num[1][j]));                vis[temp]=1;                hashs[temp]=-(num[0][i]+num[1][j]);            }        for(int i=0;i<n&&!label;i++)            for(int j=0;j<n&&!label;j++)                for(int k=0;k<n&&!label;k++)                {                    int temp=f(num[2][i]+num[3][j]+num[4][k]);       找到对应存储的地方                    if(vis[temp])  如果有标记了,说明这有个值跟我大小一样,但是因为上面是处理的相反数,所以存在有相加=0的五个数                    {                        label=true;                    }                }        if(label)            printf("Yes\n");        else            printf("No\n");    }    return 0;}