您的位置:首页 > 理论基础 > 计算机网络

hdu5491(2015合肥网络赛H题)

2015-09-28 19:17 423 查看
题意:

给出三个数字D、s1和s2,用L来表示D的二进制表示中1的个数,L在区间[s1,s2]中,我们要找到离D最近的并且大于D的一个数字,且这个数字的L也落在区间[s1,s2]中。

思路:

一直超时。。。不知道为啥,后来也不知道为啥就不超时了。。。说说不超时的代码。

对于一个数字D,我们先给它进行+1操作,看D+1是否满足L值落在区间[s1,s2]中,如果满足就输出,不满足就进行如下操作:

我们从最低位开始找,找到第一段连续的1,把这些1都变成0,然后把这些1的前面那个位置变成0,就如10111100110变成10111101000,然后我们要把最新得到的这个数的1的个数变成s1,从最低位开始补1就好了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

long long G(long long n)
{
long long tmp = n - ((n >>1) &033333333333) - ((n >>2) &011111111111);
return ((tmp + (tmp >>3)) &030707070707) %63;
}

int main() {
long long t;
long long d, s1, s2;
scanf("%I64d",&t);
for(long long kase = 1; kase <= t; kase++) {
scanf("%I64d%I64d%I64d",&d,&s1,&s2);
long long x = d + 1;
long long num = G(x);
if(num >= s1 && num <= s2) {
printf("Case #%I64d: %I64d\n",kase,x);
continue;
}
bool flag = false;
for(long long i = 1; ; i <<= 1) {
if(flag == false) {
if((d & i)) {
d -= i;
flag = true;
}
} else {
if((d & i)) {
d -= i;
flag = true;
} else {
d |= i;
break;
}
}
}
x = d;
num = G(x);
if(num >= s1 && num <= s2);
else
x |= ((1 << (s1 - num)) - 1);
printf("Case #%I64d: %I64d\n",kase,x);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: