AOJ-AHU-OJ-596 下一个K-number

下一个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 。

Input
一个整数T,表示T组数据。 (1<=T<=1000)
对于每组数据:
一个整数n。 (1<=n<=1000000000)

Output
对于每组数据,输出下一个k-number。

Sample Input
OriginalTransformed
4
1
5
16
11

Sample Output
OriginalTransformed
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

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值