C. Classy Numbers
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Let's call some positive integer classy if its decimal representation contains no more than 33 non-zero digits. For example, numbers 44, 200000200000, 1020310203 are classy and numbers 42314231, 102306102306, 72774200007277420000 are not.
You are given a segment [L;R][L;R]. Count the number of classy integers xx such that L≤x≤RL≤x≤R.
Each testcase contains several segments, for each of them you are required to solve the problem separately.
Input
The first line contains a single integer TT (1≤T≤1041≤T≤104) — the number of segments in a testcase.
Each of the next TT lines contains two integers LiLi and RiRi (1≤Li≤Ri≤10181≤Li≤Ri≤1018).
Output
Print TT lines — the ii-th line should contain the number of classy integers on a segment [Li;Ri][Li;Ri].
Example
input
Copy
4 1 1000 1024 1024 65536 65536 999999 1000001
output
Copy
1000 1 0 2
题目大意:求区间[L,R]内由不超过3个非零数组成的数字的个数,dp[i][j]表示长为i的数字由不超过j个非零数组成的数字的个数
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
ll dp[20][4];
int T;
ll l, r;
ll solve(ll num) {
if (num == 0) return 1;
vector<int> seq;
while (num > 0) {
seq.push_back(num % 10);
num /= 10;
}
int cnt = 0;
ll ans = 0;
for (int i = seq.size() - 1; i > 0; i--) {
if (seq[i]) {
if (cnt < 3) {
ans += (dp[i - 1][3 - cnt - 1] * (seq[i] - 1) + dp[i - 1][3 - cnt]);
}
else if (cnt == 3) {
ans += dp[i - 1][0];
}
cnt++;
}
}
if (cnt <= 2) ans += seq[0];
if (cnt <= 3) ans ++;
return ans;
}
int main() {
dp[0][0] = 1;
dp[0][1] = 9;
for (int i = 1; i <= 19; i++) {
dp[i][0] = 1;
for (int j = 1; j <= 3; j++) {
dp[i][j] = dp[i - 1][j] + 9 * dp[i - 1][j - 1];
}
}
for (int i = 0; i <= 19; i++) {
for (int j = 1; j <= 3; j++) {
dp[i][j] += dp[i][j - 1];
}
}
//for (int i = 0; i < 3;i ++)
// for (int j = 0; j <= 3; j++)
// cout << i << " " << j << " " << dp[i][j] << endl;
cin >> T;
while (T--) {
cin >> l >> r;
cout << solve(r) - solve(l - 1) << endl;
}
return 0;
}