考虑每一位的情况,再把它们都加起来
拿c这一位举例,分两步计算:
- 基础:c前面,共[0 - ab-1] ab种可能; c后面,共[0 - 999] 1000种可能。两者相乘 ab*1000。 这里为什么前面最高位是 ab-1 不是ab,后面会讨论考虑
- 具体考虑c的情况
2.1 k = 0,那么c前面就必须不能为0,否则这个数不存在. 之前[0 - ab-1] 种 0这种情况就要去掉,即减去1x1000 。在LQ 233 中,指定k = 1,故不用考虑这个情况
2.2 c = k,即刚好是要统计的某那个数,那么0 - def 这些也可以算进去了,加 def+1
2.3 c > k,即超过了要统计的那个数,那么前面ab这一项就可以算进来了,且后面def能取到 [0 - 999] 1000种,刚好加 1x1000
LQ 233
class Solution {
public:
int countDigitOne(int n) {
vector<int> digit;
// n: 123456
while (n) {
digit.push_back(n % 10);
n /= 10;
}
reverse(digit.begin(), digit.end());
// digit: [1, 2, 3, 4, 5, 6]
int len = digit.size();
int res = 0;
for (int i = 0; i < len; i ++) {
int left = 0;
for (int k = 0; k < i; k ++) left = left * 10 + digit[k];
int right = 0, t = 1;
for (int k = i + 1; k < len; k ++) {
right = right * 10 + digit[k];
t = t * 10;
}
int c = digit[i];
res += left * t;
if (c == 0) res += 0;
else if (c == 1) res += right + 1;
else if (c > 1) res += t;
}
return res;
}
};
AcWing 338
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Get the number of k from 1 to n
int kNumbers(int n, int k) {
if (!n) return 0;
// n = 123 answer = [3, 2, 1]
vector<int> answer;
while(n) answer.push_back(n % 10), n /= 10;
reverse(answer.begin(), answer.end());
int res = 0;
for (int i = 0; i < answer.size(); i ++) {
int left = 0, right = 0, t = 1;
for (int j = 0; j < i; j ++) left = left * 10 + answer[j];
for (int j = i + 1; j < answer.size(); j++) right = right * 10 + answer[j], t *= 10;
res += left * t;
if (k == 0) res -= t; // 0 is special
if (answer[i] == k) res += right + 1;
if (answer[i] > k) res += t;
}
return res;
}
int main() {
int a, b;
int A[10], B[10]; // A[i] means the number of i from 1 to a
while(cin >> a >> b && a != 0 && b != 0) {
if (a > b) swap(a, b);
for (int i = 0; i < 10; i ++) {
A[i] = kNumbers(a - 1, i);
B[i] = kNumbers(b, i);
cout << B[i] - A[i] << " ";
}
cout << endl;
}
return 0;
}