http://acm.hdu.edu.cn/showproblem.php?pid=5491
题目大意:给定一个数D,它的二进制数中1的个数为L,求比D大的数的最小值x且x的二进制数中1的个数num满足s1 <= num <= s2
分析:
将D+1变成n,求其二进制数中1的个数L
(1)如果L在(s1, s2)范围内,直接输出
(2)如果num<s1,从右到左找0的最小位i,将该位的0改成1(即:1的个数少了,增加一个1),n的值则增加2^i(即:n += 2^i)
(3) 如果num>s2,从右到左找1的最小位i,将该位+1(即:1的个数多了,需要减少1),n的值则增加2^i(即: n += 2^i)
从左到右找是为了保证n值最小增加
#include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> const int N = 110; typedef long long ll; using namespace std; int d[N]; int get(ll n) { int j = 0, num = 0; while(n) { d[j++] = n % 2; if(n % 2 == 1) num++; n /= 2; } return num; }//求n的二进制中1的个数 ll Pow(int a, int b) { ll ans = 1; while(b) { if(b % 2 == 1) ans *= a; a *= a; b /= 2; } return ans; }//快数幂求a的b次幂 int main() { int t, num, a, b, x = 0; ll n; scanf("%d", &t); while(t--) { x++; scanf("%I64d%d%d", &n, &a, &b); memset(d, 0, sizeof(d)); n++; num = get(n); printf("Case #%d: ", x); while(1) { if(num >= a && num <= b) { printf("%I64d\n", n); break; } else if(num < a) { int k = 0; while(d[k]) k++; d[k] = 1; n += Pow(2, k); num++; } else if(num > b) { int k = 0; while(!d[k]) k++; n += Pow(2, k); num = get(n); } } } return 0; }