ACdream 1154 Lowbit Sum(数位DP)

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 <= 10^9)
Output
每组数据输出一行,对应的ans
Sample Input
1
2
3
Sample Output
1
3
4
Solution
对于每个数,我们先把它转化为二进制;例:21–>10101
对于00001~10101,可以分为几个部分:
00001~10000
10001~10100
10101
因为对于每个数,从最右边的1截断,于是就可以理解为:
00001~10000
001~100
1
设s[i]为二进制从右边数第 i+1 个数为1 (且其他数都为0)的lowbit sum;
则 s[i]=s[i-1]*2+2^i-2^(i-1);
则lowbit sum(21)=s[0]+s[2]+s[4];
Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
ll s[100];
ll init(int n)
{
    if(s[n])
        return s[n];
    s[n]=init(n-1)*2+(1<<n)-(1<<(n-1));
    return s[n];
}
int main()
{
    int n;
    ll ans;
    memset(s,0,sizeof(s));
    s[0]=1;
    init(30);//打表 
    while(scanf("%d",&n)!=EOF)
    {
        ans=0;
        for(int i=0;n&&i<30;i++)
        {
            if(n&1) 
                ans+=s[i];
            n>>=1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(ACdream 1154 Lowbit Sum(数位DP))