07:和为给定数
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
给出若干个整数,询问其中是否有一对数的和等于给定的数。
- 输入
- 共三行:
第一行是整数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
【思路】# 结果 时间
14 Accepted 03-28
13 Accepted 03-28
12 Accepted 03-28
11 Time Limit Exceeded 03-28
10 Accepted 03-28
9 Wrong Answer 03-28
8 Time Limit Exceeded 03-28
7 Wrong Answer 03-28
6 Runtime Error 03-28
5 Runtime Error 03-28
4 Runtime Error 03-28
3 Wrong Answer 03-28
2 Compile Error 03-27
1 Wrong Answer 03-27让爸爸用血与泪的经历告诉你们这道题的思路orz
开始 我是这样想的 从那些数中 找出一个比给定数小一位的数,然后找m-比他小一位的数是否在序列中,但是还要判断比他小一位的数
是否在序列中等诸多问题(orz),然后就wrong了
后来 题解 的方法是将序列按升序排序,从第一位开始,看看m-第一位是否在序列中。。正好与我相反(orz)
然后又wrong了QAQ
有个坑 如果 2个数 1 3 给定数为2,那么就会输出1 1,这是不对的,1重复使用了。所以还要判断重复使用。在二分查找的时候,函数的返回值是他的位置
并且找到的这个位置不能等于他正在枚举的数的位置,这样就避免了、、、、
但是 又 wrong了
原来 是 移位运算的顺序0-0
l+(r-l)/2 这是我的本意 然后我用了移位运算 l+(r-l)>>1,这样是不对的
因为 (下面贴一大段qwq)
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。基本的优先级需要记住:指针最优,单目运算优于双目运算。如正负号。先乘除(模),后加减。先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7.逻辑运算最后计算。果然 我还是又wrong了。。。
原来我开始定义的long long 格式化却用的%d。。。。
最后
accepted
end(orz)
【代码】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 int n,m; 7 int a[100009]; 8 int f(int); 9 int main() 10 { 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++) 13 scanf("%d",&a[i]); 14 scanf("%d",&m); 15 sort(a+1,a+n+1);//排序 16 for(int i=1;a[i]<=m/2;i++)//枚举m/2前面的数(这样循环次数会少,因为m/2总有一个数满足) 17 { 18 if(f(m-a[i])&&f(m-a[i])!=i)//能找到这个数并且没有重复使用 19 { 20 printf("%d %d",a[i],m-a[i]); 21 return 0; 22 } 23 } 24 printf("No"); 25 return 0; 26 } 27 int f(int x)// 返回位置 28 { 29 int l=1,r=n,mid; 30 while(l<=r) 31 { 32 mid=l+((r-l)>>1);//>>1是除以2。不用(l+r)/2是为了避免l+r数据过大 33 if(a[mid]==x)return mid; 34 if(a[mid]<x)l=mid+1; 35 if(a[mid]>x)r=mid-1; 36 } 37 return 0; 38 }