kedaOJ#1479. 蒟蒻的疑问

题目描述
最近,蒟蒻小明的班上准备拍一次特殊的集体照,因为队形要求是要班上的所有32名同学全部站成一排。而好学的小明发现,在这种情况下,如果将男女生分别看成10,照相的队形就能组成一个32位长的二进制数,而二进制又能转化成十进制,因此一个不同的队形就对应了一个不同的数字。

小明想考一考他的同桌,就想出了一个问题:给定原始队形x,问如何重新排列队伍,才能得到第一个在数值上比原始队形大的数y呢。但其实身为蒟蒻的小明自己也不知道答案,所以就把计算答案这个任务委托给了聪明的你,请你写一个程序帮帮孩子。

提示:
y 是大于x的最小整数。比如对于x=13,表示原本的队形为0⋯01101,则对应的y应为14,表示新队形为0⋯01110

输入格式
输入包含若干行,每行一个整数x,表示原本的队伍组合成的数值大小,以x=0表示输入结束。

输出格式
每行一个整数,表示每个x对应的y

样例
输入数据 1

1
2
3
4
5
0

输出数据 1

2
4
5
8
6

数据范围
1≤x≤232−1

代码示例

#include<bits/stdc++.h>
using namespace std;
int main(){
    int x;
    while(cin>>x&&x){
        int y = 0;
        int t = 0;
        int n = 0;
        while(t=x&-x,x-=t,x&t<<1)y|=1<<n++;
        printf("%d\n",y|t<<1|x);
    }
    return 0;
}

代码的执行流程如下:

循环读入:通过 while 循环读入整数 x,只要 x 不为0,就继续处理。

初始化变量:

int y = 0; 初始化结果变量 y。
int t = 0; 初始化用来表示 x 的最低位的1的权值。
int n = 0; 初始化用来记录 x 的末尾0的数量。
找到最低位的1并处理:

while(t=x&-x,x-=t,x&t<<1) 的循环做了几件事:
t = x & -x; 找到 x 的最低位的1的权值。
x -= t; 从 x 中移除这个1。
x & t << 1; 检查在移除的1的左侧是否有1(即检查是否是连续的1)。
如果左侧有1,说明在这个位置上进行翻转会得到一个更大的数。
y |= 1 << n++; 如果有连续的1,则在结果 y 中对应的位置上放置1。
构造结果:

printf(“%d\n”,y|t<<1|x); 输出结果。这里 y | t << 1 | x 通过以下步骤构造下一个更大的数:
y:是原始 x 末尾0的数量对应的二进制数。
t << 1:是将 x 的最低位的1左移一位后得到的数。
x:是除了最低位的1之外, x 的剩余部分。
结束条件:

当输入的 x 为0时,结束循环。

代码执行流程如下:

  1. 循环读入:通过 while 循环读入整数 x,只要 x 不为 0,就继续处理。

  2. 初始化变量:

    • int y = 0; 初始化结果变量 y。
    • int t = 0; 初始化用来表示 x 的最低位的 1 的权值。
    • int n = 0; 初始化用来记录 x 的末尾 0 的数量。
  3. 找到最低位的 1 并处理:

    • while(t = x & -x, x -= t, x & t << 1) 的循环做了几件事:
      • t = x & -x; 找到 x 的最低位的 1 的权值。
      • x -= t; 从 x 中移除这个 1。
      • x & t << 1; 检查在移除的 1 的左侧是否有 1(即检查是否是连续的 1)。
        • 如果左侧有 1,说明在这个位置上进行翻转会得到一个更大的数。
      • y |= 1 << n++; 如果有连续的 1,则在结果 y 中对应的位置上放置 1。
  4. 构造结果:

    • printf("%d\n", y | t << 1 | x); 输出结果。这里 y | t << 1 | x 通过以下步骤构造下一个更大的数:
      • y:是原始 x 末尾 0 的数量对应的二进制数。
      • t << 1:是将 x 的最低位的 1 左移一位后得到的数。
      • x:是除了最低位的 1 之外, x 的剩余部分。
  5. 结束条件:

    • 当输入的 x 为0时,结束循环。
  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值