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

本文介绍了解决HDU 4588题目的方法,该题要求计算二进制数从a加到b的进位次数。通过观察规律,文章提出了一种有效的算法来计算特定范围内所有数的二进制表示中每位1的出现次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值