HDU 4588 2013 ACM/ICPC 南京邀请赛 C 题

/*

给你整数 a,b; 要你求a,a+1,a+2...a+b-1,使用的是二进制的加法计算,
求二进制加法过程中进位了多少次 
分析:假设 a = 0, b = 20
位i 54321 
0   00000
1   00001
2   00010
3   00011
4   00100
5   00101
6   00110
7   00111
8   01000
9   01001
10  01010
11  01011
12  01100
13  01101
14  01110
15  01111
16  10000
17  10001
18  10010
19  10011
20  10100
观察发现 pos_1 周期 2
		 pos_2 周期 4
   		 pos_3 周期 8
      	 pos_4 周期 16
然后通过计算 a->b :dp[pos_1]中1个数 
					dp[pos_2]中1个数
     				dp[pos_3]中1个数
         			dp[pos_4]中1个数 
         			。。。。。
         			这里有各种方法,我是使用dfs()搜索,注意若干特殊情况,代码中有详解 
最后通过 k += dp[i-1]/2; dp[i] += dp[i-1]/2; 进行累加计算 k  

*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
#define manx 100

__int64 dp[manx],num ;

void dfs(__int64 a,__int64 b,__int64 val,int flag){
    if(flag > 51) return;
    __int64 sum = b - a + 1; // sum 表示区间 
    __int64 ans = sum/val*(val/2); // ans表示周期个数 * 周期内1的个数 
    if(sum%val) {
        if(a%val >= val/2){ // 第一次出现 1 的时候 
        	if(sum%val>val-a%val + val/2) // 当出现1100001的情况 
         		ans += (val-a%val)+(sum%val-val+a%val-val/2);
       		else  ans += min(sum%val,val-a%val);
        }    
        else{  // 第一次出现 0 的时候 
            if(sum%val - (val/2-a%val) >= 0) { 
                if(sum%val-(val/2-a%val)<=val/2) 
                	ans += sum%val-(val/2-a%val);
               	else ans += val/2; // 当出现0011110的情况 
           	} 
        }    
    }
    dp[++num] = ans;
    dfs(a,b,val*2,flag+1);
}

int main(){
    __int64 a,b;
    while(cin>>a>>b){
        if(a>b) swap(a,b);
        memset(dp,0,sizeof(dp));
        __int64 sum = b-a+1,ans = sum/2;
        if(sum%2 && a%2) ans++; 
        num = 0; 
        dp[++num] = ans;
        dfs(a,b,2*2,1);
        __int64 k = 0;
        for(int i=1;i<100;i++){
            k += dp[i]/2;
            dp[i+1] += dp[i]/2;
        }
        cout<<k<<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值