Educational Codeforces Round 50 (Rated for Div. 2) C. Classy Numbers

看到数论就懵了,题目有两个解法,第一个解法是组合数学的内容,解析用英文写的,看不懂;第二个解法是暴力搜索的,找了网上用同样方法的中文注释代码才看明白。首先如果直接枚举肯定玩完,要找些其他办法。题目中用到了dfs,或者叫暴力搜索,但是思路很巧妙。函数设计了三个参数,分别是搜索层数lev,代表10的次方数;当前处理的数字cu,为了不越界,用long long型;非0位数的个数cnt。如果层数超过了18,就应该返回。设置一个vector,存long long型数据,每次如果没返回,就把这个数加进vector。之后用循环控制接下来的搜索过程。

代码如下。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> v;
void brute(int lev,ll cu,int cnt)    {
    if (lev==18)    {
        v.push_back(cu);
        return;
    }
    brute(lev+1,cu*10,cnt);
    if (cnt<3)  {
        for (int i=1;i<=9;i++)
            brute(lev+1,cu*10+i,cnt+1);
    }
}

int main()  {
    ios::sync_with_stdio(false);
    cin.tie(0);
    brute(0,0,0);
    v.push_back(1e18);
    ll l,r;
    int n;
    cin>>n;
    for (int i=0;i<n;i++)   {
        cin>>l>>r;
        int ans=upper_bound(v.begin(),v.end(),r)-lower_bound(v.begin(),v.end(),l);
        cout<<ans<<endl;
    }
    return 0;
}

貌似这样会有重复搜索的内容,可能会爆栈或TLE,但是每次搜索时的X10,会让这一分支不断加深,到最深后,两侧的递归树会不断伸展,直到覆盖整个10^18的所有数。这个搜索才18层,但是已经足以达到所有数字了,时间复杂度可以保证。

注意:

1.C++中的两个二分查找标准库函数:upper_bound(iterator begin,iterator end,elem)——从升序排列的顺序存储结构中寻找大于elem的第一个元素,返回指向这个元素的迭代器。如果未找到,返回指向elelm的迭代器

2.C++中的两个二分查找标准库函数:lower_bound(iterator begin,iterator end,elem)——从升序排列的顺序存储结构中寻找大于等于elem的第一个元素,返回指向这个元素的迭代器。如果未找到,返回指向elelm的迭代器

猜你喜欢

转载自www.cnblogs.com/yichuan-sun/p/9623461.html