【第22期】观点:IT 行业加班,到底有没有价值?

整数中的1(二)

原创 2015年11月19日 16:05:18
描述
给出两个非负32位整型范围内的数a,b,请输出闭区间[a,b]内所有数二进制中各个位的1的总个数。
输入
有多组测试数据
每组测试数据只有一行,是两个整型数a,b(0<=a<=b<=150000000),空格分隔。
当a,b都是0时表示输入结束,该组输入不用计算。
测试数据的组数不超过1000组
输出
对于每组输入,输出区间[a,b]内所有数二进制中各个位的1的总个数。
样例输入
1 2
100 200
0 0
样例输出
2
419


本来想到要出一道求1-n中每个数的二进制为1的个数,当n小时,按普通方法就可以了,

当n比较大就需要找规律,将1-15列出来就会发现规律了

1

10

11

100

101

110

111

1000

1001

1010

1011

1100

1101

1110

1111

当二进制位为4位的时候前面2^3个1已经确定了,后面3位就是前面1-3位二进制的和吗?

所以就可以直接预处理就结果算出来,查询的时候只需要算一段就可以了,然后那

一段就可以通过每次去掉前面那个1得到。

#include <stdio.h>
#define LL long long
const int maxn = 55;
LL cnt[maxn], sum[maxn], bit[maxn];
void print ( LL a[] )
{
    for ( int i = 0; i < maxn; i ++ )
        printf ( "%lld ", a[i] );
    printf ( "\n" );
}
//发现位数是按1 2 4 8....增长
LL get_ans ( LL n )
{
    LL ans = 0, t;
    int begin;
    while ( n > 0 )
    {
        begin = 0;
        t = n;
        while ( t >= ( 1 << begin ) )
        {
            t = t-( 1 << begin );
            ans = ans+cnt[begin];
            begin ++;
        }
        if ( t == 0 )   //有可能是2^k-1,那么t就会为0就不需要算了
            break ;
        ans = ans+t;
        n = n & bit[begin]; //去掉前面那个1
    }
    return ans;
}
int main ( )
{
    LL n, m;
    sum[0] = cnt[0] = 1;
    for ( int i = 1; i < maxn; i ++ )
    {
        cnt[i] = ( 1 << i )+sum[i-1]; //将二进制位为i的个数求出来
        sum[i] = sum[i-1]+cnt[i];   //去掉前面一个1就变成i-1,变化即为前i-1的和
        bit[i] = ( 1 << i )-1;  //2^i-1取出最后i位
    }
    while ( ~ scanf ( "%lld%lld", &n, &m ), n || m )
    {
        if ( n == 0 )   //考虑n为0
            n = 1;
        printf ( "%lld\n", get_ans ( m )-get_ans ( n-1 ) );
        //相减就可以了
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

第三周C#技术支持训练(二)自定义一个整数,输出该数分别于1-10相乘的结果

实验简述: 2.        自定义一个整数,输出该数分别于1-10相乘的结果。(使用\t控制输出格式) 源代码: using System; using System.Collection...

程序员面试题精选100题(22)-整数的二进制表示中1的个数

题目:输入一个整数,求该整数的二进制表达中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。 一个很基本的想法是,我们先判断整数的最右边一位是不是1。接着把整数右移一位,原来处于右边第二位的数字现在被移到第一位了,再判断是不是1。这样每次移动一位,直到这个整数变成0为止。现在的问题变成怎样判断一个整数的最右边一位是不是1了。很简单,如果它和整数1作与运算。由于1除了最右边一位以外,其他所有位都为0。因此如果与运算的结果为1,表示整数的最右边一位是1,否则是0。 得到的代码如下: ////////////////////////////////////

nyoj281 整数中的1(二) 数位DP

和整数中的1一毛一样。就是输入时改了一下罢了。 AC代码: #include const int maxn = 35; int w[maxn], h[maxn]; void deal(){ h[...

【100题】第二十八 整数的二进制表示中1的个数

一,题目:输入一个整数,求该整数的二进制表达中有多少个1。 <span style="color: rgb(51,51,51);"

【有趣的面试算法题】之二 求1~n的整数中1的个数,递归统计区间块中1的数量

题目:求1~n的整数中1的个数。 常规做法是,先写一个右移判1的子函数,计算每个数里面的1的个数,然后遍历1~n,取和,就是答案。 但是 采用 递归统计区间块中1的数量,并且递归深度不会超过 n 的...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)