• 1223:An Easy Problem


    1223:An Easy Problem 题目链接

    题目的要求是:

    **要使得 n 在 a 不变的情况下 ,得到任意多的 n' 满足 n' > n ,定义为集合 M ,要求取 M 中最小的 n' 为 **

    (a 代表 n 中二进制位 为 1 的个数)

    • 一种暴力做法是,统计 n 的二进制中 1 的个数为 a ,然后 设置一个变量 t = n,t 每次自增 1 (t++),

      之后,统计 t 的二进制中 1 的个数为 b , 如果 a == b,那么 t 就是 比 n 大的正整数集合 M 中,最小的数。

    • O(1) 的做法是用位运算,举个例子 :

      n == 78,我们尝试着在不改变 a 的情况下,移动 n 的二进制中的 1 , 让 n 变大的幅度尽可能的小

      序号 n n 中的二进制表示
      1 78 ‭0100 1110‬
      2 77 0100 1101
      3 89 0101 0101
      4 83 ‭0101 0011‬
      • 为了实现变大的过程,肯定要把 某个 1 向左移动,那么如何选取这个 1 呢?

        从右边开始 寻找第一段 连续的 1 (只有一个 1 也算 一段), 把将这段连续 1 中最左端的 1 向左前进 一 位

        要让这段连续 1 中的左端 前进一位 ,只要在 这段连续的 1 的右端 加 1就好了,二进制的加法进位到头

        如何寻找 右端的 1 呢?

        lowbit运算 : t1 = n & (-n) 得到最右边的 1

        ​ ‭0100 1110‬

        ​ & 1011 0010

        ​ = 0000 0010

        之后 t2 = n + t1; 得到进位之后的值。

        ​ ‭ 0100 1110‬

        ​ + 0000 0010

        ​ = 0101 0000

        但是,这么做了之后,我们就丢失了 原先那段连续 的 1 的信息了。

      • 为了让 n 变大的 幅度尽可能的小

        就要把那一段连续的 1 剩余的部分,全部移动到 最右边 (参考 序号 1 和 序号 4 的二进制表示)

        寻找那段丢失的 1 。

        ​ n ^ t2

        ​ 0100 1110‬

        ​ ^ 0101 0000

        ​ = 0001 1110

        我们发现,这样 经过 ^ 得到的结果,会多出两个 1 ,解法办法是,右移的时候,再向右移动两位就好

        即 >> 2

        (n ^ t2) / t1 ,( / t1) 这个操作是为了把 ^ 之后的 1 整个向右移动 (log_2 t1) 的位置,

        因为 t1 代表了 最右边的 1 ,且只有 1 ,在二进制表示中,肯定是 2的幂,(log_2 t1) 得到当前t1 中 1的位置

        / t1 相当于 >>(log_2 t1) ,两者相等, 之后再 >>2 消去多余的 两个 1 ,

        最后 和 t2 取 按位或 就得到了最终想要的结果。

    代码实现

    #include <bits/stdc++.h>
    using namespace std;
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0),cout.tie(0);
        int x,t1,t2,y;
        while(cin>>x){
            if(x == 0) break;
            t1 = x & (-x);  
            t2 = x + t1;
            y = t2 | ((x ^ t2) / t1) >> 2;
            cout<<y<<endl;
        }
        return 0;
    }
    

    参考: https://blog.csdn.net/u012891472/article/details/52641838

  • 相关阅读:
    HDU 4472 Count DP题
    HDU 1878 欧拉回路 图论
    CSUST 1503 ZZ买衣服
    HDU 2085 核反应堆
    HDU 1029 Ignatius and the Princess IV
    UVa 11462 Age Sort
    UVa 11384
    UVa 11210
    LA 3401
    解决学一会儿累了的问题
  • 原文地址:https://www.cnblogs.com/lukelmouse/p/10739007.html
Copyright © 2020-2023  润新知