【PNR#2 Div1 A】恰钱(数位 DP)
恰钱
题目链接:PNR#2 Div1 A
题目大意
给你一个区间,要你判断里面是否有数满足二进制 1 个数等于末尾 0 个数,如果有就找出一个。
思路
考虑直接上数位 DP,就用二进制来 DP 即可。
维护是否在碰左边界右边界,\(1\) 的个数,末尾连续 \(0\) 的个数,以及当前形成的数。
然后分 \(0,1\) 讨论一下,具体看代码。
代码
#include<cstdio>
using namespace std;
int q, l, r;
int slove(int now, bool ld, bool rd, int num1, int lst0, int val) {
if (now < 0 && val && lst0 == num1) return val;
if (lst0 + now + 1 < num1) return -1;
if (!ld && !rd) {
if (!val) return -1;
if (((num1 + 1) + 1 <= now + 1) || (num1 == lst0 + now + 1)) {
if (((num1 + 1) + 1 <= now + 1)) return val | (1 << (num1 + 1));
else return val;
}
return -1;
}
for (int i = (ld ? ((l >> now) & 1) : 0); i <= (rd ? ((r >> now) & 1) : 1); i++) {
if (i == 0) {
int x = slove(now - 1, ld & (i == ((l >> now) & 1)), rd & (i == ((r >> now) & 1)), num1, lst0 + 1, val);
if (x != -1) return x;
}
else {
int x = slove(now - 1, ld & (i == ((l >> now) & 1)), rd & (i == ((r >> now) & 1)), num1 + 1, 0, val | (1 << now));
if (x != -1) return x;
}
}
return -1;
}
int main() {
// freopen("ex_data3.in", "r", stdin);
// freopen("write.txt", "w", stdout);
scanf("%d", &q);
while (q--) {
scanf("%d %d", &l, &r);
printf("%d\n", slove(31, 1, 1, 0, 1, 0));
}
return 0;
}

浙公网安备 33010602011771号