<题目链接>
题目大意:
对于那些各个位数上的非0数小于等于3的数,我们称为 classy number ,现在给你一个闭区间 [L,R] (1≤L≤R≤1018).,问你这个区间内有多少个classy number 数。
解题分析:
对于这种对数的数位有要求的题目,可以往搜索,dp上想一想,本题可用搜索做。先用搜索将所有符合条件的数放入vector ,然后排序,再用二分函数得到 L,R的坐标,再相减,即可得到 [L,R]区间中满足条件的数的个数。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int T; long long l, r; vector<long long> v; void dfs(int dep, long long res, int n) { //dep记录递归的深度,即res的位数,n表示res数中!=0的数字个数 v.push_back(res); if(dep==18) return; //下面分两种情况dfs dfs(dep+1,res*10,n); //下一位仍然为0 if(n<3){ for(int i=1;i<=9;++i) dfs(dep+1,res*10+i,n+1); //下一位不为0 } } int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); //可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率 cin >> T; for(int i=1;i<=9;++i) dfs(1,i,1); //按首位为i的数字向下进行递归 //上面的预处理将所有18位及其一下的所有 符合条件的数全部加入vector v.push_back(1e18); //注意1e18有19位,所以要将1e18单独加入 vector sort(v.begin(), v.end()); while(T--) { cin >> l >> r; cout << upper_bound(v.begin(),v.end(),r)-lower_bound(v.begin(),v.end(),l) << endl; //因为这是闭区间,所以一个用upper_bound,一个用lower_bound } return 0; }