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