您的位置:首页 > 其它

HDU 4588 Count The Carries(数学 找规律)

2013-09-04 21:18 337 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4588

这个题目规律还是好找的,具体实现好好想想也不难,但是要注意,进位可能会到60位,要注意,尽量让数组下标在不越界的情况下取最大

题目意思很简单,看题目给的例子就看出来了,给定a b  :  a<b 求二进制a a+1 a+2 .....b求和的过程中其二进制的进位次数,开始想暴力下,

后来一看范围还是算了,老老实实找规律吧,其实这个题目找的就是ab区间内所有数组二进制每一位的1出现的次数,然后我们可以发现这样

一个规律第一位循环2,第二位循环为4

也就是

00000

00001

00010

00011

00100

00101

00110

00111

竖着看,发现规律了吧!

最后求解答案的时候不用分开求,直接求b--0的和a-1--0的,然后直接相减就OK 了!

#include <iostream>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#define LL __int64
using namespace std;
#define maxn 200
LL num[maxn],a,b,num_a,num_b,num_c,ans,mod;
LL my_pow(LL a,LL b){
LL ans=a;
b--;
while(b--){
ans*=a;
}
return ans;
}
int init(){
for(int i=0;i<61;i++)
num[i]=my_pow(2,i+1);
return 0;
}
int main(){
int i,j,k;
init();
while(scanf("%I64d%I64d",&a,&b)!=EOF){
ans=num_c=0;
a--;
if(a<=0) a=0;
for(i=0;i<60;i++){
mod=(a+1)%num[i];
num_a=((a+1)/num[i])*(num[i]/2)+(mod > (num[i]/2) ? (mod-num[i]/2) : 0);
mod=(b+1)%num[i];
num_b=((b+1)/num[i])*(num[i]/2)+(mod > (num[i]/2) ? (mod-num[i]/2) : 0);
num_b=num_c+num_b-num_a;
num_c=num_b/2;
ans+=num_c;
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU 数学