模拟+位运算 HDOJ 5491 The Next
题意:意思很简单,找一个最接近D且比D大的数,满足它的二进制表示下的1的个数在[S1, S2]之间
分析:从D + 1开始,若个数小于S1,那么从低位向高位把0替换成1直到S1就是最小值,否则往更大的数去找,此时目标是减少1的数量,可以优化, +lowbit (D),因为+小于lowbit (D)只会增加1的数量。这题比赛时队友想的很复杂,方法不够简单暴力。
/************************************************ * Author :Running_Time * Created Time :2015/9/28 星期一 09:19:08 * File Name :H.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-8; int b[64]; int low_bit(int i) { return i & (-i); } int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { int S1, S2; ll D; scanf ("%I64d%d%d", &D, &S1, &S2); memset (b, 0, sizeof (b)); int n = 0, j = 0; D++; do { ll tmp = D; j = 0; n = 0; while (tmp) { if (tmp & 1) { b[j++] = 1; n++; } else b[j++] = 0; tmp >>= 1; } if (n < S1) { int add = S1 - n; j = 0; while (add) { if (!b[j]) b[j] = 1, add--; j++; } break; } else D += low_bit (D); }while (n < S1 || n > S2); ll ans = 0, x = 1; for (int i=0; i<64; ++i) { if (b[i]) ans += x; x <<= 1; } printf ("Case #%d: %I64d\n", ++cas, ans); } return 0; }
编译人生,运行世界!