poj 2549 Sumsets

Sumsets
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10551 Accepted: 2873

Description

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

Sample Output

12
no solution

Source

提示

题意:

给你一个数的集合,从这些数中找出a+b+c=d,且输出最大d的值。

思路:

类似a1*x1*x1*x1+a2*x2*x2*x2+。。。。。。

我们可以得出a+b=d-c,之后a+b的值用哈希表存下来,之后用d-c去找用没有相同的值,注意它们都不是同一个数。也可以用a+b去进行二分查找,下面给出两种做法。

示例程序

哈希表的做法:

Source Code

Problem: 2549		Code Length: 1478B
Memory: 31732K		Time: 532MS
Language: GCC		Result: Accepted
#include <stdio.h>
#include <string.h>
struct
{
    int bug,sum,x,y;					//bug表示该位置是否有数据
}hash[100000][20];
int a[1000],max;
void insert(int x,int y)
{
    int i=0,sum,key;
    sum=a[x]+a[y];
    key=abs(sum)%100000;				//sum可能为负数,要用绝对值
    while(hash[key][i].bug==1)
    {
        i++;
    }
    hash[key][i].bug=1;
    hash[key][i].sum=sum;
    hash[key][i].x=x;
    hash[key][i].y=y;
}
void find(int x,int y)
{
    int i=0,sum,key;
    sum=a[x]-a[y];
    key=abs(sum)%100000;
    for(i=0;hash[key][i].bug==1;i++)
    {
        if(x!=hash[key][i].x&&y!=hash[key][i].y&&x!=hash[key][i].y&&y!=hash[key][i].x&&sum==hash[key][i].sum&&a[x]>max)		//判断它们有没有同一个数的且比最大值大
        {
            max=a[x];
            return;
        }
    }
}
int main()
{
    int i,i1,n;
    scanf("%d",&n);
    while(n!=0)
    {
        max=-1000000007;
        memset(hash,0,sizeof(hash));
        for(i=0;n>i;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=0;n>i;i++)
        {
            for(i1=0;n>i1;i1++)
            {
                if(i!=i1)
                {
                    insert(i,i1);			//打表
                }
            }
        }
        for(i=0;n>i;i++)
        {
            for(i1=0;n>i1;i1++)
            {
                if(i!=i1)
                {
                    find(i,i1);				//哈希查找
                }
            }
        }
        if(max!=-1000000007)
        {
            printf("%d\n",max);
        }
        else
        {
            printf("no solution\n");
        }
        scanf("%d",&n);
    }
    return 0;
}
二分查找,要比哈希不知好到哪去(可能哈希算法写的不是很好,这个和平常所见到的二分不太一样):

Source Code

Problem: 2549		Code Length: 1213B
Memory: 392K		Time: 0MS
Language: G++		Result: Accepted
#include <cstdio>
#include <algorithm>
using namespace std;
int a[1000];
int f(int sum,int r)					//和平常不一样的二分(也不知道是不是二分了)
{
    int l=0;
    while(l<r)
    {
        if(a[l]+a[r]==sum)
        {
            return 1;
        }
        else if(a[l]+a[r]>sum)
        {
            r--;
        }
        else
        {
            l++;
        }
    }
    return 0;
}
int main()
{
    int i,i1,i2,n,smax,t,sum;
    scanf("%d",&n);
    while(n!=0)
    {
        smax=-1000000007;
        for(i=0;n>i;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);						//排序
        for(i=n-1;i>=0;i--)					//从大到小比较好,找到就可以跳出了
        {
            for(i1=n-1;i1>=0;i1--)
            {
                if(i!=i1)
                {
                    sum=a[i]-a[i1];				//枚举右边
                    if(f(sum,i1-1)==1)
                    {
                        smax=a[i];
                        break;
                    }
                }
            }
            if(smax!=-1000000007)
            {
                break;
            }
        }
        if(smax==-1000000007)
        {
            printf("no solution\n");
        }
        else
        {
            printf("%d\n",smax);
        }
        scanf("%d",&n);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值