题目链接:https://ac.nowcoder.com/acm/problem/15291
分析:由于这道题的l 和 r的上线都很接近于int上限,觉得类型转换比较烦,所以索性把所有数据都声明为long long了
在1e10里面的幸运数字个数为 2+2^2+2^3+2^4+...+2^10 数量级大概2的11次左右,很小。所以我们是可以大表存下所有1e10以内的幸运数的,当然最后还要加一个4444444444,否则r=1e10,就找不到大于1e10的幸运数了。
之后对于这个幸运数数组从小到大排序,用二分去查找l和r在其中的相对位置(当然用lower_bound和upper_bound)
然后对于范围中的每一个幸运数字:
ans += ( min ( a[i] , r) - l + 1) * a[i];
注意的是 这个l要实时更新。
具体看了代码都能明白的:

#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define ll long long
using namespace std;
#define close_stdin  ios::sync_with_stdio(false)
ll l, r,ans=0;
ll a[100005];
int cnt = 2;
void dfs(ll x) {
    if (x > 10000000000) { return; }
    if (x > 10) { a[cnt++] = x; }
    dfs(x * 10 + 4);
    dfs(x * 10 + 7);
}
void solve() {
    a[0] = 4;
    a[1] = 7;
    dfs(4);
    dfs(7);
    a[cnt] = 4444444444;
    sort(a, a + cnt + 1);
    cin >> l >> r;
    int L = lower_bound(a, a + cnt + 1, l)-a;
    int R = upper_bound(a, a + cnt + 1, r) - a;
    for (int i = L;i <= R;i++) {
        ans += (min(a[i], r) - l + 1) * a[i];
        l = a[i] + 1;
    }
    cout << ans<<"\n";
}
int main() {
    close_stdin;//只是为了让cin和printf一样快
    solve();
}

谢谢浏览哈!