先贴代码,以后再写题解。。。

 

首先,直接枚举肯定是会超时的,毕竟n就有10^9那么多。。。

对于每个数,我们先把它转化为二进制;例: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];

 

设i=4;即 10000;

可分为 :

00001~01000   s[i-1];

01001~01111   s[i-1]-lowbit(01000)=s[i-1]-2^(i-1);  (从最右边的1截断,即可理解为 00001~00111 )

10000       lowbit(10000)=2^i;

 

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 
 9 ll s[100];
10 
11 ll init (int n){
12     if (s[n])
13         return s[n];
14     s[n]=init (n-1)*2-(1<<(n-1))+(1<<n);//cout<<s[n]<<" ";
15     return s[n];
16 }
17 
18 int main (){
19     int n;    //while (cin>>n&&n) cout<<(1024>>n)<<endl;
20     ll ans=1;
21     int temp=2;
22     memset (s,0,sizeof s);
23     s[0]=1;
24     init (30);    //for (int i=0;i<=30;i++) cout<<s[i]<<" ";
25     while (~scanf ("%d",&n)){
26         ans=0;
27         for (int i=0;n&&i<30;i++) {
28             if (n&1)
29                 ans+=s[i];//cout<<ans<<endl;
30             n>>=1;
31             //n/=2;
32         }
33         printf ("%lld\n",ans);
34     }
35     return 0;
36 }

 

posted on 2014-07-31 17:19  gfc  阅读(288)  评论(0编辑  收藏  举报