通过lowbit快速求得一个数的二进制状态下哪些位是1

62 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

二进制哪几位是1

原理:借助lowbitlowbit的思想,每次得到最后一个11的位置并减去。

lowbit(n)100...0lowbit(n)(100...0)到这是第几位,需要取对数log2(lowbit(n))log_2(lowbit(n))即可。

但是C++ math.hC++\ math.h库的loglog是以ee为底数的实数运算且复杂度常数较大,故采用哈希思想,H[i]H[i]的值为log2ilog_2i

于是有:

#include <iostream>
using namespace std;
const int MAX_N = 1 << 20;
int H[MAX_N + 1];
void init()
{
    for (int i = 0; i <= 20; i++)
    {
        H[1 << i] = i;
    }
}
void prtOne(int n)
{
    while (n)
    {
        cout << H[n & -n] << ' ';
        n -= n & -n;
    }
    puts("");
}
int main()
{
    init();
    int n;
    while (cin >> n)
        prtOne(n);
    return 0;
}

还有稍微复杂一点但效率更高的方法,不需要使用2201062^{20}\approx10^6的数组,利用一个数学小技巧:k[0,35],2k mod 37\forall k\in[0,35], 2^k\ mod\ 37互不相等且恰好取遍整数1361\sim36

H[i]=kH[i]=k说明2k2^k%37=i,修改后如下:

#include <iostream>
using namespace std;
int H[37];
void init()
{
    for (int i = 0; i < 36; i++)
        H[(1ll << i) % 37] = i;
}
void prtOne(int n)
{
    while (n)
    {
        cout << H[(n & -n) % 37] << ' ';
        n -= n & -n;
    }
    puts("");
}
int main()
{
    init();
    int n;
    while (cin >> n)
        prtOne(n);
    return 0;
}

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…