ZOJ 3962

就是统计1~n中出现的各个数字的次数,当然是在16进制下。

不过有个区间问题的小技巧,统计从 [x,y] 可以转换成 从 [1,y] 减去 [1,x-1]。

不过要分类讨论一下,因为有可能会出现溢出,从ffffffff +1 得到 00000000 就是溢出了。

因为 n < 1e9 所以只会溢出一次。

#include<cstdio>
#include<cmath>
#include<cctype>

const int cost[] = {6,2,5,5,4,5,6,3,
                    7,6,6,5,4,5,5,4};

long long solve(long long n, int k) {
    long long i = 1;   // 位数
    long long cnt = 0;
    long long low = 0;
    long long tmp = n;
    while(n) {
        long long t = n % 16;
        n /= 16;
        low = tmp % i;
        if(t < k) {
            cnt += n*i;
        } else if(t > k) {
            cnt += (1+n)*i;
        } else {
            cnt += n*i;
            cnt += low+1;
        }
        i *= 16;
    }
    return cnt;
}
int Hex(char c){
    if(isdigit(c))
        return c-'0';
    return c - 'A' + 10;
}
int main() {
    int t;
    scanf("%d",&t);
    for(int i=0;i<t;i++){
        long long n;
        long long x=0;
        char str[15];
        scanf("%lld%s",&n,str);
        for(int i=0;i<8;i++)
            x = (x<<4) + Hex(str[i]);
        long long cnt = 0;
        long long ans = 0;

        if((n-1)+x <= 4294967295ll){ // 没有溢出
            long long tmp;
            for(int i=1;i<16;i++){
                tmp = solve((n-1ll)+x,i);
                cnt += tmp;
                ans += tmp*cost[i];
            }
            for(int i=1;i<16;i++){
                tmp = solve(x-1,i);
                cnt -= tmp;
                ans -= tmp*cost[i];
            }
            ans += (n*8-cnt)*cost[0];
        }else {
            long long tmp;
            for(int i=1;i<16;i++){
                tmp = solve(4294967295ll,i);
                cnt += tmp;
                ans += tmp*cost[i];
            }
            for(int i=1;i<16;i++){
                tmp = solve(x-1,i);
                cnt -= tmp;
                ans -= tmp*cost[i];
            }
            for(int i=1;i<16;i++){
                tmp = solve((n-2ll)+x-4294967295ll,i);
                cnt += tmp;
                ans += tmp*cost[i];
            }
            ans += (n*8-cnt)*cost[0];
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/kongbb/p/10702004.html
ZOJ
今日推荐