zoukankan      html  css  js  c++  java
  • 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 }

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

  • 相关阅读:
    HDU 3081 Marriage Match II
    HDU 4292 Food
    HDU 4322 Candy
    HDU 4183 Pahom on Water
    POJ 1966 Cable TV Network
    HDU 3605 Escape
    HDU 3338 Kakuro Extension
    HDU 3572 Task Schedule
    HDU 3998 Sequence
    Burning Midnight Oil
  • 原文地址:https://www.cnblogs.com/acgoto/p/9033817.html
Copyright © 2011-2022 走看看