Digit sum [B进制]

Digit sumDigit\ sum

题目描述见链接 .


\color{red}{正解部分}

按位处理, 设当前进制为 BB, 计算第 bitbit 位的答案,
这道题 作基础, 可以知道形如 0,0,..1,1..,2,2,..B1,B10,0,..1,1..,2,2,..B-1,B-1 的循环节长度为 cir_len=Bbit+1cir\_len=B^{bit+1},
循环节内部最长连续数字为 BbitB^{bit} 个,
完整的循环节个数为 cir_num=N+1Bbit+1cir\_num=\frac{N+1}{B^{bit+1}}, 对答案贡献B(B1)2Bbitcir_num\frac{B(B-1)}{2}*B^{bit}*cir\_num .

还剩余一个不完整的循环节, 长度为 sca_num=(N+1)%Bbit+1sca\_num = (N+1)\%B^{bit+1}, 在这个循环节中, 将形如 1,1,..11,1,..1 看成新的循环节,
得到新的 cir_len=Bbitcir\_len = B^{bit}, cir_num=sca_numBbitcir\_num=\frac{sca\_num}{B^{bit}}, 对答案贡献cir_num(cir_num1)2cir_len\frac{cir\_num(cir\_num-1)}{2}*cir\_len,

然而还是会剩下不完整的形如 2,22, 2 这样的小循环节, 长度为 left_num=sca_num%cir_lenleft\_num = sca\_num \% cir\_len,
答案贡献left_numcir_numleft\_num * cir\_num .


\color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register

int N;
int B;
int Ans;
int Case_cnt;
int pw[20][21];

void Work(){
        scanf("%d%d", &N, &B);
        Ans = 0;
        for(reg int bit = 0; pw[B][bit] <= N+1; bit ++){
                int cir_len = pw[B][bit+1];
                int cir_num = (N+1) / cir_len; 
                Ans += pw[B][bit] * cir_num * B*(B-1)/2;
                int sca_num = (N+1) % cir_len;
                if(!sca_num) continue ;
                cir_len = pw[B][bit];
                cir_num = sca_num / cir_len;
                Ans += cir_len * cir_num*(cir_num-1)/2;
                int left_num = sca_num % cir_len;
                Ans += left_num * cir_num;
        }
        printf("Case #%d: %d\n", ++Case_cnt, Ans);
}

void Init(){
        for(reg int i = 2; i <= 11; i ++){
                pw[i][0] = 1;
                for(reg int j = 1; j <= 20; j ++) pw[i][j] = pw[i][j-1] * i;
        }
}
int main(){
        int T;
        scanf("%d", &T);
        Init();
        while(T --) Work();
        return 0;
}
posted @ 2019-09-15 20:55  XXX_Zbr  阅读(120)  评论(0编辑  收藏  举报