Sumsets uva+hash表的应用

Sumsets

Given S, a set of integers, find the largest d such that a + b + c = d where a, b, c, and d are distinct elements of S.

Input

Several S, each consisting of a line containing an integer 1 <= n <= 1000 indicating the number of elements in S, followed by the elements of S, one per line. Each element of S is a distinct integer between -536870912 and +536870911 inclusive. The last line of input contains 0.

Output

For each S, a single line containing d, or a single line containing "no solution".

Sample Input

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

Output for Sample Input

12
no solution

解决方案:题目意思就不用讲了。直接枚举的话肯定不行的,a+b+c=d,可以将其分成两半,a+b,d-c。先枚举a+b,存至哈希表,再枚举d、c,看两边是否相等,而推出d。

代码:

#include<iostream>
#include<map>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int MAXN = 10000003;
const int MAXSIZE = 1030;

int n;
int rear;

struct node
{
	int i, j;
	int sum;
}st[MAXSIZE*MAXSIZE];

int first[MAXN], next[MAXSIZE*MAXSIZE];
int A[MAXSIZE];



int Hash(int s){
    int h=s&0x7fffffff;
    return h%MAXN;

}///对sum进行哈希编码,
void init()
{
	rear = 0;
	memset(first, -1, sizeof(first));
}
int Find(int i, int j, int s)
{
	int h = Hash(s);
	for(int v = first[h]; v != -1; v = next[v])
	{
		if(s == st[v].sum && st[v].i != i && st[v].i != j && st[v].j != i && st[v].j != j) return 1;
	}
	return 0;
}///寻找符合条件的A[i]-A[j];
void Insert(int s)
{
	int h = Hash(st[s].sum);
	next[s] = first[h];
	first[h] = s;
}///形成一个并查集,以便储存形成一个sum的多个i,j;

int main(){

    while(~scanf("%d",&n)&&n){
    memset(next,0,sizeof(next));

    for(int i=0;i<n;i++){
    scanf("%d",&A[i]);
    }
    init();
    sort(A,A+n);///对它进行排序,以便对A[i]-A[j]的组合可从A[i]的最大数开始查询

    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++){
        st[rear].sum=A[i]+A[j];
        st[rear].i=i;st[rear].j=j;
        Insert(rear);
        rear++;
        }
       bool flag=true;
    for(int i=n-1;i>=0;i--){
       for(int j=0;j<n;j++)if(i!=j){
       if(Find(i,j,A[i]-A[j]))///由于前面对A[]进行的排序,所以查到的第一个符合的就是最大的那个
      {printf("%d\n",A[i]);flag=false;break;}
       }
     if(!flag) break;
    }
       if(flag)
       printf("no solution\n");
    }


    return 0;}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值