ACdream 1154 Lowbit Sum(数位DP)

来源:互联网 发布:jquery.ajaxqueue.js 编辑:程序博客网 时间:2024/05/20 01:12

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;}
0 0