题目链接:http://codeforces.com/contest/437/problem/B
题目意思:给出两个整数 sum 和 limit,问能否从1 ~ limit 这些数中选出一些数(注意:这些数最多只能取一次!),使得它们的lowbit 之和 等于 sum。不能则输出 -1。
这题总的来说比较直接。一开始犯了个比较傻的错误,以为除了2的幂以外,其他的 lowbit 都是1。还有一点需要注意的是,代码中 if (sum - t >= 0) 很重要!因为偶数的lowbit参差不齐,有可能sum-t 变为负数的!总后往前贪(limit ----> 1),能保证每次贪的数是最大的!这样也能尽快结束循环,防止超时。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 1e5 + 5; 10 int ans[maxn]; 11 12 int main() 13 { 14 int sum, limit; 15 while (cin >> sum >> limit) 16 { 17 memset(ans, 0, sizeof(ans)); 18 int t, cnt = 0, tot = 0; 19 for (int i = limit; i >= 1; i--) // 从大到小开始贪心 20 { 21 if (i % 2 == 0) 22 { 23 int count = 0; 24 for (int j = i; !(j & 1); j >>= 1) // 从右往左看,1第一次出现的位置 25 count++; 26 t = pow(2.0, count); // 求出该偶数的lowbit 27 if (sum - t >= 0) // 该数的lowbit能组成sum的条件 28 { 29 sum -= t; 30 ans[i] = 1; 31 tot++; 32 } 33 } 34 else 35 { 36 sum--; // 奇数的lowbit是1 37 ans[i] = 1; 38 tot++; 39 } 40 if (!sum) 41 break; 42 } 43 if (sum) 44 printf("-1 "); 45 else 46 { 47 printf("%d ", tot); 48 for (int i = 1; i <= limit; i++) 49 { 50 if (ans[i]) 51 printf("%d ", i); 52 } 53 printf(" "); 54 } 55 } 56 return 0; 57 }