hdu - 4321 - Arcane Numbers 2 - 数位统计

来源:互联网 发布:淘宝红酒怎么那么便宜 编辑:程序博客网 时间:2024/05/17 08:35

题意:http://acm.hdu.edu.cn/showproblem.php?pid=4321

    给定a和b、n,让你求b + a, b + 2 * a, .......b + n * a里面有多少1.

题解:

   这个题解是以前做过多校之后看的。以前看了很久很久很久很久都没看懂。 现在二十分钟左右看懂了。 是我以前心不在焉吗?

按位统计计算,如果枚举 那么复杂度就是 64 * N
第一条
当统计第K位的时候 可以注意到 第 B+T*A 和 B+(T+2^(K+1))*A 位是相同的
那么 第K位的时候 只需要统计2^(K + 1)  - 1次就可以了

第二条
当统计第K位的时候 可以注意到 连续的 (2^K)/A都是连续的0 或者连续的1 所以可以考虑直接连续记录(2^K)/A个结果。

那么 第K位的时候 只需要统计N / ((2^K)/A)次就可以了

综合 第一条 第二条 那么 第K位的时候 只需要统计 2^K/((2^K)/A) 复杂度 变为O(A)

总复杂度为64*A

#include <cstdio>#include <cstring>int main(){    int t;    __int64 a, b, n;    scanf("%d", &t);    for(int cas=1; cas<=t; ++cas){        scanf("%I64d%I64d%I64d",&a,&b,&n);        __int64 cnt = 0;        __int64 max = b + a * n;        for(__int64 i=0; i<64; ++i){ // 一位一位统计            __int64 m = 1LL << i;            __int64 mm = m;            if(m > max)                break;            m <<= 1;            __int64 cur = a + b;            __int64 j = 0;            while(j < m && j < n){                __int64 upper = cur + (mm - (cur % mm)) - 1LL;                __int64 step = (upper - cur) / a + 1LL;                if(j + step >= n){                    step = n - j;                }                if(j + step >= m){                    step = m - j;                }                if(cur & (1LL << i)){                    cnt += step * (n / m);                    if(j + step < (n % m)){                        cnt += step;                    }else if(j < (n % m)){                        cnt += ( n % m ) - j;                    }                }                cur += a * step;                j += step;            }        }        printf("Case #%d: %I64d\n", cas, cnt);    }    return 0;}


原创粉丝点击