ポータル
Luogu
問題解決のためのアイデア
まず、すべての幸運の数字を構築しました。
そして、ラッキーナンバーはあまり貢献しています考えます。
数の\(X \)間隔で、(\ [L、R]) \の数がの倍数である\(\ lfloorの\のFRAC {R \ lceil \ FRAC {L} - } {X} \ rfloor X} {\ + rceil。1 \) 。
その後、我々はただ、各貢献のためのラッキーナンバーは一度カウントできる必要があります。。。。。???
しかし、答えはノーです。
同じ数が倍のより幸運数であってもよいので、我々はこれらの幸運の数字のLCMの包含と除外する必要があるため、共感は、他のラッキーナンバーラッキーナンバー倍の前に除去することがとても良いです。
詳細注意事項
- この問題に注意を払うことは、データ範囲揚げ、いくつかの状況かもしれ
long double
見つけること。
参照コード
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define int long long
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
}
const int LIM = 10000000000;
const int _ = 100002;
int n, vis[_], luck[_], l, r, ans;
inline void dfs1(int x) {
if (x > LIM) return ;
if (x != 0) luck[++n] = x;
dfs1(x * 10 + 6), dfs1(x * 10 + 8);
}
inline void init() {
dfs1(0);
sort(luck + 1, luck + n + 1);
for (rg int i = 1; i <= n; ++i)
for (rg int j = i + 1; j <= n; ++j)
if (luck[j] % luck[i] == 0) vis[j] = 1;
int tmp = 0;
for (rg int i = 1; i <= n; ++i)
if (!vis[i]) luck[++tmp] = luck[i];
n = tmp;
sort(luck + 1, luck + n + 1, greater < int > ());
}
inline int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; }
inline int f(int x) { return r / x - (l / x + (l % x != 0 ? 1 : 0)) + 1; }
inline void dfs(int x, int cnt, int Lcm) {
if (x == n + 1) {
if (Lcm != 1) ans += (cnt % 2 == 1 ? 1 : -1) * f(Lcm); return ;
}
dfs(x + 1, cnt, Lcm);
long double _Lcm = 1.0 * Lcm / gcd(Lcm, luck[x]) * luck[x];
if (_Lcm > r) return ;
dfs(x + 1, cnt + 1, _Lcm);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
init();
read(l), read(r);
dfs(1, 0, 1);
printf("%lld\n", ans);
return 0;
}
エンドSahua \(qwq \)