uva10125 Sumsets

4 篇文章 0 订阅

看似简单的题,其实要求考虑的非常严密

首先如果枚举a,b,c再判断d的话肯定超时,即使用hash存d也一样,解决办法是根据a+b=d-c先把所有d-c的值用hash存起来,再枚举所有a+b,这样枚举量就减小到1000*999了。

然后,每组a,b和每组c,d都必须考虑,不能先排序再枚举1000*999/2,因为d不一定是四个数字中最小的。

最后,当a+b==d-c时,还必须判断他们互不相等。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define HASHSIZE 10000003
#define MAX 5000000
using namespace std;
int s[1000],head1[HASHSIZE],next1[MAX],s1[MAX][2];

int hash(int value)
{
    if(value<0)
        value=-value;
    return (value)%HASHSIZE;
}

void insert(int i,int j,int t)
{
    int sum=s[j]-s[i];
    int hashvalue=hash(sum);
    int u=head1[hashvalue];
    while(u!=-1)
    {
        u=next1[u];
    }
    next1[t]=head1[hashvalue];
    head1[hashvalue]=t;
}
int find(int i,int j)
{
    int all=s[i]+s[j];
    int hashvalue=hash(all);
    int u=head1[hashvalue];
    while(u!=-1)
    {
        if(s[s1[u][1]]-s[s1[u][0]]==all&&s[s1[u][1]]!=s[i]&&s[s1[u][1]]!=s[j]&&s[s1[u][0]]!=s[i]&&s[s1[u][0]]!=s[j])
            return s[s1[u][1]];
        u=next1[u];
    }
    return -1000000000;
}
int main()
{
    int n,i,j,t,flag,help,large;
    while(scanf("%d",&n)&&n)
    {
        flag=0;
        large=-1000000000;
        memset(head1,-1,HASHSIZE*4);
        for(i=0;i<n;i++)
        {
            scanf("%d",&s[i]);
        }
        //sort(s,s+n);
        t=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(i==j)
                    continue;
                s1[t][0]=i;
                s1[t][1]=j;
                insert(i,j,t);
                t++;
            }
        }
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(i==j)
                    continue;
                if((help=find(i,j))!=-1000000000)
                {
                    flag=1;
                    if(help>large)
                        large=help;
                }
            }
        }
        if(flag==0)
            printf("no solution\n");
        else
            printf("%d\n",large);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值