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); } }