数字统计题解
题目理解
题目要求计算所有不大于 N 的非负整数中数字 D 出现的总次数。例如,当 D=1 且 N=12 时,数字1出现在1、10、11(两次)、12中,共5次。
输入输出分析
输入格式:
-
两个正整数 D 和 N,其中1≤D≤9,1≤N<1016。
输出格式:
-
一个整数,表示数字 D 在所有不大于 N 的非负整数中出现的总次数。
解题思路
为了高效计算数字 D 在1到N之间的出现次数,可以采用逐位统计的方法。具体步骤如下:
-
逐位处理:
-
对于数字的每一位(个位、十位、百位等),分别统计该位上数字 D 出现的次数。
-
假设当前处理的是第k位(从右到左,个位为第1位),计算该位上 D 出现的次数。
-
-
统计方法:
-
将数字分为三部分:高位、当前位、低位。
-
根据当前位的值与 D 的关系,分情况计算:
-
如果当前位小于 D,则高位决定该位上 D 出现的次数。
-
如果当前位等于 D,则高位和低位共同决定该位上 D 出现的次数。
-
如果当前位大于 D,则高位加1决定该位上 D 出现的次数。
-
-
-
特殊情况处理:
-
当 D=0 时,需要额外处理,因为数字的最高位不能为0。
-
AC代码:
#include <bits/stdc++.h>
using namespace std;
long long ans(long long n, int d) {
long long cnt = 0;
long long x = 0, y = 0, z = 0;
long long sum = 1;
while (n / sum > 0) {
x= n - (n / sum) * sum;
y = (n / sum) % 10;
z = n / (sum * 10);
if (y < d) {
cnt += z * sum;
} else if (y == d) {
cnt += x * sum + x + 1;
} else {
cnt += (x + 1) * sum;
}
if (d == 0) {
cnt-= sum;
}
sum *= 10;
}
return cnt;
}
int main() {
int D;
long long N;
cin >> D >> N;
cout << ans(N, D) << endl;
return 0;
}