题目链接: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();
}
谢谢浏览哈!

京公网安备 11010502036488号