Codeforces 702B Powers of Two

题目链接:http://codeforces.com/problemset/problem/702/B

题意:

  给你N个数a0, a1, a2......an-1,问存在几对 <i,j> 满足i < j, ai + aj = 2x ,x可以是任意整数.

思路:  

  最容易想到的是把这 n  个数全部两两加起来,然后判断是否是 2 的幂,但是这需要O(n2),题目给的 n <= 1e5,所以会TLE.再思考思考ai + aj = 2x ,那么变下形: aj = 2x - ai ,这样只需要枚举2x,然后用2x - ai ,在剩余的a[i + 1] ~ a[n - 1]个数中查找存在多少个aj 就可以解决问题了.由于给定的ai <= 1e9, 即ai + aj< 231,所以 x 的枚举范围是从 0 到30.查找的时候利用二分查找优化查找时间,总的时间复杂度为O(30*n*logn),可以满足题目的时间限制。

注意:

   结果会超出int,在这里吃了一记WA. 

代码:

 1#include  <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <stack>
 7 #include <queue>
 8 #include <vector>
 9 #include <algorithm>
10 #include <string>
11 #define mearv(a, b) memset(a, b, sizeof(a))
12 #define mestrc(a, b, c) memset(&(a), b, sizeof(c))
13 
14 typedef long long LL;
15 using namespace std;
16 const int MAXN = 100000;
17 
18 int main() {
19     int atw[33] = {0};
20     for(int i = 0; i <= 30; i++) atw[i] = 1 << i;//枚举2的次幂
21     int n;
22     scanf("%d", &n);
23     int num[MAXN + 3] = {0};
24     for(int i = 0; i < n; i++)
25         scanf("%d", &num[i]);
26     sort(num, num + n);//二分查找要求数列有序
27     long long ans = 0;
28     for(int i = 0; i < n - 1; i++) {
29         for(int j = 0; j <= 30; j++) {
30             int key = atw[j] - num[i];
31             int low = lower_bound(num + i + 1, num + n, key) - num;//返回第一个大于等于key的位置
32             int cnt = 0;
33             if(num[low] == key) {//判断是否能找到key
34                 int up = upper_bound(num + i + 1, num + n, key) -num;//返回第一个大于key的位置
35                 cnt = up - low;//两个位置的差就是数列中key的个数
36             }
37             ans += cnt;
38         }
39     }
40     printf("%I64d
", ans);
41     return 0;
42 }
原文地址:https://www.cnblogs.com/Ash-ly/p/5720532.html