Classy Numbers
题目描述
Let’s call some positive integer classy if its decimal representation contains no more than 3 3 3 non-zero digits. For example, numbers 4 4 4, 200000 200000 200000, 10203 10203 10203 are classy and numbers 4231 4231 4231, 102306 102306 102306, 7277420000 7277420000 7277420000 are not.
You are given a segment [ L ; R ] [L; R] [L;R]. Count the number of classy integers x x x such that L ≤ x ≤ R L \le x \le R L≤x≤R.
Each testcase contains several segments, for each of them you are required to solve the problem separately.
输入格式
The first line contains a single integer T T T ( 1 ≤ T ≤ 1 0 4 1 \le T \le 10^4 1≤T≤104) — the number of segments in a testcase.
Each of the next T T T lines contains two integers L i L_i Li and R i R_i Ri ( 1 ≤ L i ≤ R i ≤ 1 0 18 1 \le L_i \le R_i \le 10^{18} 1≤Li≤Ri≤1018).
输出格式
Print T T T lines — the i i i-th line should contain the number of classy integers on a segment [ L i ; R i ] [L_i; R_i] [Li;Ri].
题面翻译
定义一个数字是“好数”,当且仅当它的十进制表示下有不超过 3 3 3 个 1 ∼ 9 1 \sim 9 1∼9 之间的数字。
举个例子: 4 , 200000 , 10203 4,200000,10203 4,200000,10203 是“好数”,而 4231 , 102306 , 7277420000 4231,102306,7277420000 4231,102306,7277420000 不是好数。
给定 [ l , r ] [l,r] [l,r],问:有多少个 x x x 使得 l ≤ x ≤ r l \le x \le r l≤x≤r,且 x x x 是“好数”?
一共有 T T T 组数据,对于每次的询问,输出一行一个整数表示答案。
样例 #1
样例输入 #1
4
1 1000
1024 1024
65536 65536
999999 1000001
样例输出 #1
1000
1
0
2
数据规模与约定
1
≤
T
≤
1
0
4
1 \le T \le 10^{4}
1≤T≤104
1
≤
l
i
≤
r
i
≤
1
0
18
1 \le l_i \le r_i \le 10^{18}
1≤li≤ri≤1018
原题
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[20][20]; // dp记录[pos][not_0_cnt]状态下的满足条件的个数
int a[20]; // a[]记录数字串
ll dfs(int pos, int not_0_cnt, bool bound, bool lead_0) // pos为此时的位置,not_0_cnt表示不是0的个数,bound表示前面每一位是否都是上界,lead_0表示是否前面全是0
{
if (pos == 0) // 枚举完每一位时返回
{
if (not_0_cnt <= 3)
return 1;
else
return 0;
}
if (!bound && dp[pos][not_0_cnt] != -1) // 读取记忆(doge
return dp[pos][not_0_cnt];
int max_num; // 可枚举的该位的数的上界
if (bound)
max_num = a[pos];
else
max_num = 9;
ll res = 0; // 统计此时的答案
for (int i = 0; i <= max_num; i++)
{
if (lead_0 && i == 0)
res += dfs(pos - 1, 0, bound && (i == a[pos]), 1);
else
res += dfs(pos - 1, not_0_cnt + (i != 0), bound && (i == a[pos]), 0);
}
if (!bound && !lead_0) // 没在边界时,记录下该状态对应的答案,记忆化
dp[pos][not_0_cnt] = res;
return res;
}
ll solve(ll x)
{
int len = 0; // 数字长度
while (x)
{
a[++len] = x % 10;
x /= 10;
}
return dfs(len, 0, 1, 1);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
memset(dp, -1, sizeof(dp)); // 将dp数组初始化为-1,表示对应状态的答案目前还未计算出
int t;
cin >> t;
ll l, r;
while (t--)
{
cin >> l >> r;
cout << solve(r) - solve(l - 1) << '\n';
}
return 0;
}