幸运数字只由4和7组成 一开始想要去打表 感觉也没问题 每次二分查找 更新边界就可以了
因为数字是由4和7组成 很容易发现规律
4 7 44 47 74 77 444 447很像队列 每次用队首拓展出两个新元素 规律如下
ll tmp1 = q.front() * 10 + 4, tmp2 = q.front() * 10 + 7;
q.pop();
q.push(tmp1);
q.push(tmp2);
那么后面就很简单了 每次更新范围 判断l,r和tmp1,tmp2的大小关系 一共只有六种:
- l > tmp2;(这个需要先判断 不然会导致错误 因为l > tmp2 == l > tmp1)
- r <= tmp1;
- l <= tmp1 && r <= tmp2;
- l <= tmp1 && r > tmp2;
- l > tmp1 && r <= tmp2;
- l > tmp1 && r > tmp2;
每次依照这个范围更新答案就可以了 代码如下
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main () {
ios::sync_with_stdio(0), cin.tie(0);
int l, r;cin >> l >> r;
ll ans = 0;
auto bfs = [&]() -> void {
queue<ll> q;
q.push(0);
while (q.size()) {
ll tmp = q.front();
q.pop();
ll tmp1 = tmp * 10 + 4;
ll tmp2 = tmp * 10 + 7;
q.push(tmp1);
q.push(tmp2);
//一共六种情况
if (l > tmp2) continue;
else if (r <= tmp1) {
ans += 1ll * (r - l + 1) * tmp1;
break;
}
else if (l <= tmp1 && r <= tmp2) {
ans += 1ll * (tmp1 - l + 1) * tmp1 + 1ll * (r - tmp1) * tmp2;
break;
}
else if (l <= tmp1 && r > tmp2) {
ans += 1ll * (tmp1 - l + 1) * tmp1 + 1ll * (tmp2 - tmp1) * tmp2;
l = (tmp2 + 1ll);
}
else if (l > tmp1 && r <= tmp2) {
ans += 1ll * (r - l + 1) * tmp2;
break;
}
else if (l > tmp1 && r > tmp2) {
ans += 1ll * (tmp2 - l + 1) * tmp2;
l = (tmp2 + 1ll);
}
}
};
bfs();
cout << ans << '\n';
}