HDU - 4334 Trouble(哈希)

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

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

然后遇到了这道题,参考了大佬的哈希函数,琢磨了一阵子,感觉自己真菜鸡(一开始想着用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;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值