Sumsets(UVA10125)整数集合

发布时间 2023-11-25 15:12:47作者: L1ngYi

备课的时候发现了这道题,对于初识哈希来说并不算一道很简单的题。在查阅林厚从老师的示例代码与往届OI选手的博客后,大致理解了本题的思路。

相关标签: Hash

跳转至本题

Description

给定一个整数集合S,求一个最大的d,满足a+b+c=d,其中a,b,c,d∈S

Input

多组数据,每组数据包括:

  • 第一行一个整数n,代表元素个数
  • 下面n行每行一个整数,代表集合元素

输入结束的标志为n=0。

Output

对于每组数据,输出:

  • 一行,如果有解,输出一个整数,代表最大的d;否则输出no solution

Sample Input

5
2
3
5
7
12
5
2
16
64
256
1024
0

Sample Output

12
no solution

Hint

n≤1000,保证输入的集合元素互不相同。

集合中的元素∈[-536 870 912,536 870 911]。

 

解题思路

a,b,c,d。共四个数,如果想采用最简单枚举法,复杂度将来到O(n4)。题目数据来说,一定会超时。

考虑题目数据量约在103,O(n2)的做法差不多能够接受。考虑做以下方法:找到两组对,使得  d-c = a+b 。若等式满足,更新d的最大值即可。

如何快速找到、定位两组值?考虑使用Hash方法。即先用n2的时间(两重循环)枚举a+b,并将其打包成对,以a+b的值为key,存入Hash数组中。

再用n2的时间(两重循环)枚举d-c,并将b-c的值作为键,在Hash数组中查找是否存在。如果能找到key相同的node点,则找到了一组满足 d-c = a+b的值。(注意检查a b c d 四个数不重复)

此时,维护ans更新为更大的d值即可。如果找不到此组合,则输出no solution

通过代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf -536870912
using namespace std;

const int maxM=1000007;
const int maxN=1010;

int n;
int hash1[3*maxM], a[maxN]; //hash table  --  source data
struct node{
    int key,x1,x2,next;
}data[maxN * maxN]; //hash node

int main(){
    while(scanf("%d",&n) && n){
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        memset(hash1,0,sizeof(hash1));
        memset(data,0,sizeof(data));
        int k=0;
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                data[++k].key=a[i]+a[j]; data[k].x1=i; data[k].x2=j;
                int x=data[k].key % maxM;
                if(x<0) x=-x;
                while(hash1[x]>0) {
                    x=x+1;
                    x=x % maxM;
                }
                hash1[x]=k;
            }
        }
        int ans=inf;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) if(j!=i){
                int key=a[i]-a[j];
                int x=key % maxM;
                if(x<0) x=-x;
                int p=x;
                int flag=0;
                while(hash1[p]>0 && !flag){
                    int p1=hash1[p];
                    if (data[p1].key==key && data[p1].x1!=i && data[p1].x2!=i && data[p1].x1!=j && data[p1].x2!=j) flag=1;
                    else {
                        p=p+1; p = p%maxM;
                    };
                } 
                if(hash1[p]>0 && a[i]>ans) ans=a[i]; 
            }
        }
        if(ans!=inf) cout<<ans<<endl;
        else cout<<"No Solution"<<endl;
    }
}