【题目链接】
ybt 1244:和为给定数
OpenJudge NOI 1.11 07:和为给定数
【题目考点】
1. 二分:查找某个数是否存在
代码模板为:
while(l <= r)
{
m = (l+r)/2;
if(a[m] > x)
r = m-1;
else if(a[m] < x)
l = m+1;
else
break;//找到解
}
【解题思路】
指定的加和为
m
m
m。
对数字序列进行升序排序后,遍历这个数字序列。
每遍历到一个数字
a
i
a_i
ai,通过二分查找看序列中是否存在数字
m
−
a
i
m-a_i
m−ai。
二分查找时,左端点
l
l
l要设为i+1,右端点
r
r
r为
n
n
n。如果
l
l
l为1,
r
r
r为
n
n
n,则当
a
i
∗
2
=
m
a_i*2=m
ai∗2=m时,会找到自己,而数组中实际上不存在两个
a
i
a_i
ai,这是不符合题意的。
如果存在这个数字,那么输出数对
a
i
a_i
ai与
m
−
a
i
m-a_i
m−ai,程序结束。如果到最后也没有输出过数对,输出"No"。
【题解代码】
解法1:二分:查找数字是否存在
#include <bits/stdc++.h>
using namespace std;
#define N 100005
int main()
{
int n, m, a[N], num;
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i];
cin >> m;
sort(a+1, a+1+n);//升序排序
for(int i = 1; i <= n && a[i] < m; ++i)//a[i]:数对中较小的数字
{
num = m - a[i];//看看数列中是否存在num这个数字,如果存在,那么数对为a[i], num
int l = i+1, r = n, mid;//二分查找,是否存在a[mid]值为num (如果l为1,r为n,可能找到自己i,当a[i]*2==m时,条件也能过,这是不符合题意的)
while(l <= r)
{
mid = (l + r) / 2;
if(a[mid] > num)
r = mid - 1;
else if(a[mid] < num)
l = mid + 1;
else
{//输出结果
cout << a[i] << ' ' << num;
return 0;
}
}
}
cout << "No";
return 0;
}
解法2:使用stl binary_search函数
#include <bits/stdc++.h>
using namespace std;
#define N 100005
int main()
{
int n, m, a[N], num;
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i];
cin >> m;
sort(a+1, a+1+n);//升序排序
for(int i = 1; i <= n && a[i] < m; ++i)//a[i]:数对中较小的数字
{
num = m - a[i];//看看数列中是否存在num这个数字,如果存在,那么数对为a[i], num
if(binary_search(a+i+1, a+1+n, num))//如果a[i+1]~a[n]存在数字num
{//输出结果
cout << a[i] << ' ' << num;
return 0;
}
}
cout << "No";
return 0;
}