[HDOJ4588]Count The Carries(数学,规律)

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

题意:从a加到b,每次结果加到a上,看在二进制下一共发生了多少次进位。

把0到n的所有数二进制下下来,可以发现规律:第一位循环节为2,每次循环01。第二位循环节是4,每次循环0011。以此类推。

计算两个数的各位分别出现了多少次1,再减掉。模拟进位统计进位次数就可以。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int maxn = 10100;
 6 LL a, b;
 7 LL vis1[maxn], vis2[maxn];
 8 LL vis[maxn];
 9 
10 void f(LL* vis, LL x) {
11     memset(vis, 0, sizeof(vis));
12     for(LL i = 1; i <= 62; i++) {
13         LL t = (1LL << i);
14         LL div = x / t;
15         LL rem = x % t;
16         LL cnt = div * (1LL << (i - 1LL));
17         cnt += (rem + 1LL) > (t / 2LL) ? rem + 1 - t / 2LL : 0LL;
18         vis[i] = cnt;
19     }
20 }
21 
22 int main() {
23     // freopen("in", "r", stdin);
24     // freopen("out.txt", "w", stdout);
25     while(~scanf("%lld%lld",&a,&b)) {
26         f(vis1, a-1); f(vis2, b);
27         memset(vis, 0, sizeof(vis));
28         for(LL i = 1; i <= 62; i++) {
29             vis[i] = vis2[i] - vis1[i];
30         }
31         LL ret = 0;
32         for(LL i = 1; i <= 63; i++) {
33             ret += vis[i] / 2LL;
34             vis[i+1] += vis[i] / 2LL;
35         }
36         printf("%lld
", ret);
37     }
38     return 0;
39 }
原文地址:https://www.cnblogs.com/kirai/p/6792441.html