您的位置:首页 > 其它

hdu 4588 Count The Carries

2013-08-20 12:05 302 查看
思路:容易发现二进制表示的数的最低位规律是01010101……;接着是001100110011……;接着是:0000111100001111……

这样我们发现每一位的循环节是2^(i+1),前2^i是0,后面的是1.这样就可以算出每一位1出现的次数。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll __int64
using namespace std;
ll a[35]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,
16777216,33554432,67108864,134217728,268435456,536870912,1073741824,
2147483648,4294967296,8589934592,17179869184};
ll sa[35],sb[35],s[100];
int get(int n)
{
int bit=0;
while(n){
bit++;
n>>=1;
}
return bit;
}
void solve(int n,ll *aa)
{
ll i,j,nn=n+1;
if(n<=0) return;
int len=get(n);
for(int k=0;k<len;k++){
aa[k]+=nn/a[k+1]*a[k];
j=nn%a[k+1];
if(j>=a[k]) j-=a[k];
else j=0;
aa[k]+=j;
}
}
int main()
{
int n,m,len1,len2;
ll c;
while(scanf("%d%d",&n,&m)!=EOF){
memset(sa,0,sizeof(sa));
memset(sb,0,sizeof(sb));
memset(s,0,sizeof(s));
solve(m,sa);
solve(n-1,sb);
for(int i=0;i<35;i++) s[i]=sa[i]-sb[i];
ll ans=0;
for(int i=0;i<100;i++){
c=(s[i]>>1);
ans+=c;
s[i+1]+=c;
}
printf("%I64d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: