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

题意: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值