下一个K-number
Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 64 MB
Description
我们首先定义一种k-number。
对于某一个数,在二进制表示中,如果有k位为1,则这个数称为k-number。
如:14=(1110)2 ,则14被称为3-number。
现如今给一个正整数n,如果n是k-number,则求出下一个k-number m。
即不存在num是k-number,且n < num < m 。
对于某一个数,在二进制表示中,如果有k位为1,则这个数称为k-number。
如:14=(1110)2 ,则14被称为3-number。
现如今给一个正整数n,如果n是k-number,则求出下一个k-number m。
即不存在num是k-number,且n < num < m 。
Input
一个整数T,表示T组数据。 (1<=T<=1000)
对于每组数据:
一个整数n。 (1<=n<=1000000000)
对于每组数据:
一个整数n。 (1<=n<=1000000000)
Output
对于每组数据,输出下一个k-number。
Sample Input
Original | Transformed |
4 1 5 16 11
Sample Output
Original | Transformed |
2 6 32 13
Hint
Sample 3:16=(10000)2,下一个1-number是 32=(100000)2
Sample 4:11=(1011)2,下一个3-number 是 13=(1101)2
Sample 4:11=(1011)2,下一个3-number 是 13=(1101)2
Source
安徽大学第五届ACM/ICPC程序设计竞赛 现场赛
————————————————————肚饿的分割线————————————————————
思路:思路非常清晰。这道题就是位运算嘛!经过缜密的思考之后发现:在二进制下寻找“01”的位置。然后将其改成“10”。因为输入不会是0,所以一定找得到1。找到1之后,找到1前面最近的0即可。这之间可能有很多的1,但是不要紧,cou一下就行了。最后将这之间的1移到最低位,保证这是紧随其后的“下一个”k-number。
代码如下:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int cas;
scanf("%d", &cas);
while(cas--) {
int k, u, i, j;
scanf("%d", &k);
for(i = 0;;i++) {
u = k | 1 << i;
if(u == k) break;//从最低位开始找到第一个1
}
int cou = 0;
for(j = i+1;;j++) {
u = k | 1 << j;
if(u != k) break;//从找到的1开始找到第一个0,若不是0,统计这之间1的个数
else cou++;//刚开始做此题你可能想不到要把夹在中间的1移到最低位
}
k |= 1 << j;
k ^= 1 << j-1;//将01改成10
if(cou) {
int one = 0;
for(int a = 0; a < cou; a++)
one |= 1 << a;
k &= ~(one << i);//将10后面紧随其后的1全部抹成0
k |= one;//将抹掉的1移至最低位
}
printf("%d\n", k);
}
return 0;
}