做法:dfs+容斥

思路

  • 先找出只含6和8的数,再把那些成倍数关系的给删了

  • 我们知道对于一个幸运号码x,在[l,r]中x的倍数的个数,就是

  • 之后根据容斥(奇加偶减),答案为选1个幸运号码−选2个幸运号码的lcm+选3个幸运号码的lcm...

  • 注意:

1.在求lcm的时候会爆long long,可以转化成long double
2.找出那些不成倍数关系的幸运号码的时候要用从大到小排序,否则会T(我也不知道是什么玄学)

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp(aa,bb) make_pair(aa,bb)
#define _for(i,b) for(int i=(0);i<(b);i++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,b,a) for(int i=(b);i>=(a);i--)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define X first
#define Y second
#define lowbit(a) (a&(-a))
#define debug(a) cout<<#a<<":"<<a<<"\n"
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef long double ld;
const int N=100010;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
const double PI=acos(-1.0);

ll l,r,ans;
set<ll> s;
vector<ll> g;

void dfs(ll n){
    if(n*10+6<=r) s.insert(n*10+6),dfs(n*10+6);
    if(n*10+8<=r) s.insert(n*10+8),dfs(n*10+8);
}

void dfs2(int dep,int cnt,ll val){
    if(val>r) return;
    if(dep==g.size()){
        if(cnt) ans+=(r/val-(l+val-1)/val+1)*((cnt&1)?1:-1);
        return;
    }
    dfs2(dep+1,cnt,val);    
    ld temp=1.0*val/__gcd(val,g[dep])*g[dep];
    if(temp<=r) dfs2(dep+1,cnt+1,temp);
}

void solve(){
    cin>>l>>r;
    dfs(0);
    for(auto x:s){
        bool flag=1;
        for(auto y:g){
            if(x%y==0){
                flag=0;
                break;
            }
        }
        if(flag) g.pb(x);
    }
    reverse(g.begin(),g.end());
    dfs2(0,0,1);
    cout<<ans<<"\n";
}


int main(){
    ios::sync_with_stdio(0);cin.tie(0);
//    int t;cin>>t;while(t--)
    solve();
    return 0;
}