Digit sum
题目描述见链接 .
正解部分
按位处理, 设当前进制为 B, 计算第 bit 位的答案,
有 这道题 作基础, 可以知道形如 0,0,..1,1..,2,2,..B−1,B−1 的循环节长度为 cir_len=Bbit+1,
循环节内部最长连续数字为 Bbit 个,
完整的循环节个数为 cir_num=Bbit+1N+1, 对答案贡献为 2B(B−1)∗Bbit∗cir_num .
还剩余一个不完整的循环节, 长度为 sca_num=(N+1)%Bbit+1, 在这个循环节中, 将形如 1,1,..1 看成新的循环节,
得到新的 cir_len=Bbit, cir_num=Bbitsca_num, 对答案贡献为 2cir_num(cir_num−1)∗cir_len,
然而还是会剩下不完整的形如 2,2 这样的小循环节, 长度为 left_num=sca_num%cir_len,
对 答案贡献 为 left_num∗cir_num .
实现部分
#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;
}