题目链接: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 }