bzoj 1853 容斥 + 搜索

思路:先把所有幸运数字找出来, 把没有用的去掉,然后爆搜容斥,因为最多只会搜十几个就超过限制了,

所以是可行的。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg
using namespace std;

const int N = 5000 + 7;
const int M = 5e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;

LL a[N], b[N], L, R, ans;
int tot, top;

void init(LL val) {
    if(val > R) return;
    if(val) a[++tot] = val;
    init(val * 10 + 6);
    init(val * 10 + 8);
}

void dfs(int p, int cnt, LL lcm) {
    if(p > top) {
        if(cnt & 1) ans += R / lcm - (L - 1) / lcm;
        else if(cnt) ans -= R / lcm - (L - 1) / lcm;
        return;
    }
    dfs(p + 1, cnt, lcm);
    long long tmp = lcm / __gcd(b[p], lcm);
    if(1.0 * b[p] * tmp <= R) dfs(p + 1, cnt + 1, b[p] * tmp);
}

int main() {
    scanf("%lld%lld", &L, &R);
    init(0);
    sort(a + 1, a + 1 + tot);
    for(int i = 1; i <= tot; i++) {
        bool flag = true;
        for(int j = 1; j <= top; j++) {
            if(a[i] % b[j] == 0) {
                flag = false;
                break;
            }
        }
        if(flag) b[++top] = a[i];
    }
    reverse(b + 1, b + 1 + top);
    dfs(1, 0, 1);

    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/CJLHY/p/9593649.html