来源:牛客网

题目描述

定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。
比如说,47、744、4都是幸运数字而5、17、467都不是。
定义next(x)为大于等于x的第一个幸运数字。给定l,r,请求出next(l) + next(l + 1) + ... + next(r - 1) + next(r)。

输入描述:

两个整数l和r (1 <= l <= r <= 1000,000,000)。

输出描述:

一个数字表示答案。
思路:选或不选/选1还是选2,且遍历的范围很小(<20)-->先用DFS遍历获得所有结果(当然可以剪枝,即超过r的数字最多只保留一个就行)存储到数组中
然后仔细观察数据,会发现:
a    next(a)
0        0
1        4
2        4
3        4
4        4
5        7
6        7
7        7
8        44
...
以样例1的2,7为例,推算一下,会发现,ans=(4-2+1)*4+(7-4)*7;
再多带几组数据进去,就能推出下面代码中的式子(标红部分)
总体难度不难,DFS很常规,唯一难一点的可能就是底下ans的推导了
这里贴一道相似的问题,也是类似于选或不选/选1还是选2,且遍历的范围很小(<20)的问题1008-「金」点石成金_2021秋季算法入门班第六章习题:搜索与搜索剪枝

代码如下
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
ll l,r,ans;
vector<ll>q; //用于存储含4和7的数字
void DFS(int i){
    q.push_back(q[i]*10+4);
    if((q[i]*10+4)>=r) return ; //剪枝
    q.push_back(q[i]*10+7);
    if((q[i]*10+7)>=r) return ; //剪枝
    DFS(i+1);
}
int main(){
    scanf("%lld%lld",&l,&r);
    q.push_back(0);
    DFS(0);
    int n=q.size();
    int i=0;
    while(q[i]<l){ //这里遍历是不会超时的,因为r最大为1000,000,000,即q里面的数字的数量最多不超过2^10+1;
        i++;
    }
    ans+=((min(r,q[i])-l+1)*q[i]);
    while(q[i]<r){
        ans+=((min(r,q[i+1])-max(q[i],l))*q[i+1]);
        i++;
    }
    printf("%lld\n",ans);
    return 0;
}