您的位置:首页 > 其它

Hdu 4588 Count The Carries(数位统计)

2014-11-07 18:41 429 查看
题目链接

Count The Carries

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 1047 Accepted Submission(s): 349



[align=left]Problem Description[/align]
One day, Implus gets interested in binary addition and binary carry. He will transfer all decimal digits to binary digits to make the addition. Not as clever as Gauss, to make the addition from a to b, he will add them one by one
from a to b in order. For example, from 1 to 3 (decimal digit), he will firstly calculate 01 (1)+10 (2), get 11,then calculate 11+11 (3),lastly 110 (binary digit), we can find that in the total process, only 2 binary carries happen. He wants to find out that
quickly. Given a and b in decimal, we transfer into binary digits and use Implus's addition algorithm, how many carries are there?

[align=left]Input[/align]
Two integers a, b(0<=a<=b<1000000000), about 100000 cases, end with EOF.

[align=left]Output[/align]
One answer per line.

[align=left]Sample Input[/align]

1 2
1 3
1 4
1 6


[align=left]Sample Output[/align]

0
2
3
6


[align=left]Source[/align]
2013 ACM-ICPC南京赛区全国邀请赛——题目重现

题意:给定两个数a,b。统计在计算a+a+1+....b的过程中,二进制的情况下共有多少次进位?

题解:要解决问题,首先要计算出区间 [a,b] 的所有数字,二进制表示下的第0位有多少个1,第1位有多少个1,直至最高位有多少个1。这个用数位统计的方法很容易解决。

在数位统计的过程中,假设是满二叉树,我们可以直接O(1)计算出这棵满二叉树各层的1的个数。对于非满二叉树上的1,我们要统计它出现的次数即可。

详情见代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef __int64 LL;
LL use[70],vis[70];
LL a,b;
LL dfs(int id,bool man)
{
if(id==-1)
return 1;
if(!man)
{  //满二叉树直接计算
for(int j=0;j<id;j++)
use[j]+=(1<<(id-1));
return (1<<id);
}
LL re=0;
LL end=0;
if(id>=1&&((1<<(id-1))&b))
end=1;
for(int i=0;i<=end;i++)
{
re+=dfs(id-1,i==end);
}
if((LL(1)<<id)&b)
use[id]+=re;
return re;
}
LL go(int id,bool man)
{
if(id==-1)
return 1;
if(!man)
{
for(int j=0;j<id;j++)
vis[j]+=(1<<(id-1));
return (1<<id);
}
LL re=0;
LL end=0;
if(id>=1&&((1<<(id-1))&a))
end=1;
for(int i=0;i<=end;i++)
{
re+=go(id-1,i==end);
}
if((LL(1)<<id)&a)
vis[id]+=re;
return re;
}
int main()
{
int i;
while(scanf("%I64d%I64d",&a,&b)!=EOF)
{
memset(use,0,sizeof(use));
memset(vis,0,sizeof(vis));
LL ix;
if(a>0)
a--;
dfs(32,true);
go(32,true);
LL ans=0;
ix=0;
for(i=0;i<=64;i++)
{
ans+=(use[i]-vis[i]+ix)/2;
ix=(use[i]-vis[i]+ix)/2;
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: