您的位置:首页 > 其它

hdu 4588 Count The Carries 数学

2015-05-26 09:08 417 查看
题目链接: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);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: