hdu 4588 Count The Carries 数学

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4588

 

题意:

以二进制加法形式算 a + (a+1) + (a+2) + ... + b

统计之中有多少次进位

 

想法:

算从1加到b和从1加到(a-1)的每一位上各有多少次进位 分别存到ca和cb

然后两个数组的对应位置相减得到从a加到b每一位上各有多少次进位 存到cc

最后再从右往左模拟一次加法运算即可

 

算进位次数的话就是列出前几项以后观察规律 不难推出公式

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>

using namespace std;

typedef long long ll;

const int maxn = 110;

ll cnt[maxn];
ll ca[maxn], cb[maxn], cc[maxn];

void init()
{
    cnt[1] = 2;
    for(int i = 2; i <= 63; i++)
        cnt[i] = cnt[i-1] * 2;
}


int main()
{
    //freopen("in.txt", "r", stdin);

    int a, b;
    init();
    while(scanf("%d%d", &a, &b) == 2)
    {
        if(a == 0)
            a = 1;
        if(b == 0)
            b = 1;

        a++, b++;//之所以要这样是因为后面写搓了 所以把a和b整体往后挪一位

        memset(ca, 0, sizeof(ca));
        memset(cb, 0, sizeof(cb));
        memset(cc, 0, sizeof(cc));

        for(int i = 1; i <= 63; i++)
        {

            ca[i] = ((a-1) / cnt[i] * (cnt[i] / 2)) + max(0LL, (a-1) % cnt[i] - cnt[i] / 2);
            if((a-1) / cnt[i] == 0)
                break;
        }

        for(int i = 1; i <= 63; i++)
        {
            cb[i] = ((b) / cnt[i] * (cnt[i] / 2)) + max(0LL, (b) % cnt[i] - cnt[i] / 2);
            if(b / cnt[i] == 0)
                break;
        }

        for(int i = 1; i <= 63; i++)
            cc[i] = cb[i] - ca[i];

        ll ans = 0;
        ll pre = 0;
        for(int i = 1; i <= 63; i++)
        {
            ans += (cc[i] + pre) / 2;
            pre = (cc[i] + pre) / 2;
        }

        printf("%I64d\n", ans);

    }
}

 

posted @ 2015-05-26 09:08  地鼠地鼠  阅读(244)  评论(0编辑  收藏  举报