信息学奥赛一本通(1244:和为给定数)

1244:和为给定数


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 8206     通过数: 3053

【题目描述】

给出若干个整数,询问其中是否有一对数的和等于给定的数。

【输入】

第一行是整数n(0 < n ≤ 100,000),表示有n个整数。

第二行是n个整数。整数的范围是在0到10^8之间。

第三行是一个整数m(0≤m≤2^30),表示需要得到的和。

【输出】

若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行No。

【输入样例】

4
2 5 1 4
6

【输出样例】

1 5

【分析】

        这道题本身并不难,首先看题目,题目说:若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。很好想到两个整数,小在前,大在后,如果我们排好序,就很容易实现这一点。其次,我们想到线性查找(枚举),i 指向第一个数,j 指向 i+1,然后一次查找a[i]+a[j]==m。很可惜,从数据规模上看,枚举必定超时。

【参考代码1】枚举超时版

#include <stdio.h>
#include <stdlib.h>
#define N 100010
int a[N];
int cmp(const void*a,const void*b)
{
	return *(int*)a-*(int*)b;
}
int main()
{
    int i,j,m,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    	scanf("%d",&a[i]);
    scanf("%d",&m);
    qsort(a,n,sizeof(int),cmp);

    for(i=0;i<n-1;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if(a[i]+a[j]==m)
			{
				printf("%d %d\n",a[i],a[j]);
				return 0;
			}
		}
	}
	printf("No\n");
    return 0;
}

        查找的方法有两种,一种是线性查找(枚举),另一种则是折半查找(分治)。

【参考代码2】

#include <stdio.h>
#include <stdlib.h>
#define N 100010
int a[N];
int cmp(const void*a,const void*b)
{
	return *(int*)a-*(int*)b;
}
int main()
{
    int i,j,m,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    	scanf("%d",&a[i]);
    scanf("%d",&m);
    qsort(a,n,sizeof(int),cmp);

    i=0;
	j=n-1;
	while(i<=j)
	{
		if(a[i]+a[j]>m)
			j--;
		else if(a[i]+a[j]<m)
			i++;
		else
		{
			printf("%d %d\n",a[i],a[j]);
			return 0;
		}
	}
	printf("No\n");
    return 0;
}

http://ybt.ssoier.cn:8088/problem_show.php?pid=1244

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值