ACM_lowbit

lowbit

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

long long ans = 0;
for(int i = 1; i < = n; i ++)
    ans += lowbit(i)
lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数
比如lowbit(7),7的二进制位是111,lowbit(7) = 1,6 = 110(2),lowbit(6) = 2,同理lowbit(4) = 4,lowbit(12) = 4,lowbit(2) = 2,lowbit(8) = 8,每输入一个n,求ans

Input:

多组数据,每组数据一个n(1 <= n <= 5*10^8)

Output:

每组数据输出一行,对应的ans.

Sample Input:

1
2
3

Sample Output:

1
3
4
解题思路:lowbit函数来源于树状数组,其含义是得到该数的二进制从右往左第一个非0位所表示的10进制数。这道题直接暴力枚举相加肯定是会超时的,因此需要推导一下有无求和公式。首先简单暴力输出前1000个数的lowbit值,其中int lowbit(int x){return x&-x;}发现有如下规律:
1 3 5 7 9 ...... lowbit(i)=20
2 6 10 14 18 ......lowbit(i)=21
4 12 20 28 36 ......lowbit(i)=22
8 24 40 56 72 ......lowbit(i)=23
从上表中,可以知道每一行的lowbit值是相等的。
拿n=9举个栗子:第一行有5个数,ans+=5*1,ans=5;第二行中有2个数,ans+=2*2,ans=9;第三行中有1个数,ans+=1*4,ans=13;第四行中有1个数,ans+=1*8,ans=21;求和完毕。现在的问题就是求解每一行有多少个lowbit值相等的数字,从所举栗子来看,假设p是所在行的lowbit值的指数,每一行有mp个数(数字的大小在n的范围内),则p=0时,m0=(9-20)/(20+1)+1=8/2+1=5;当p=1时,m1=(9-21)/(21+1)+1=7/4+1=2;当p=2时,m2=(9-22)/(22+1)+1=5/8+1=1;当p=3时,m3=(9-23)/(23+1)+1=1/16+1=1。而(int)log2(9)=3,即刚好枚举到p=3这一行,所以每一行在n的范围内相同lowbit值的数字求和公式为∑((n-2i)/(2i+1)+1)*2i,OK,推导完毕!
AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n;
 6     while(cin>>n){
 7         int p=log2(n);long long ans=0;
 8         for(int i=0;i<=p;++i)
 9             ans+=((n-(1<<i))/(1<<(i+1))+1)*(1<<i);
10         cout<<ans<<endl;
11     }
12     return 0;
13 }

 注意:左移<<运算符的优先级比双目运算符-还低,因此要加括号。

原文地址:https://www.cnblogs.com/acgoto/p/9033817.html