莫比乌斯 板子(基于kuangbin模板)

莫比乌斯经典求解问题: [a, b] 和 [c, d] 中有多少对数的gcd == k.
BZOJ - 2301
板子:

typedef long long ll;
const int maxn = 1e5+5;
bool vis[maxn];
int pri[maxn], mu[maxn], phi[maxn], sum[maxn];
void init() {   // 预处理莫比乌斯(前缀), 以及素数
    Fill(vis, true); vis[1] = false;
    mu[1] = 1; int cnt = 0;
    for (int i = 2 ; i < maxn ;  i ++) {
        if (vis[i]) {
            pri[++cnt] = i;
            mu[i] = -1;
        }
        for (int j = 1 ; j <= cnt ; j ++) {
            if (i*pri[j] > maxn) break;
            vis[i * pri[j]] = false;
            if (i % pri[j]) mu[i * pri[j]] = -mu[i];
            else {
                mu[i * pri[j]] = 0;
                break;
            }
        }
    }
    sum[0] = 0;
    for (int i = 1 ; i < maxn ; i ++) {
        sum[i] = sum[i-1] + mu[i];
    }
}
// 找[1, n], [1, m] 内互质的数的对数
ll cal(int n, int m) {
    ll ans = 0;
    if (n > m) swap(n, m);
    for (int i = 1 , la = 0 ; i <= n ; i = la + 1) {
        la = min(n/(n/i), m/(m/i));
        ans += 1ll*(sum[la] - sum[i-1]) * (n/i) * (m/i);
    }
    return ans;
}
void solve() {
    int a, b, c, d, k;
    scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
    ll ans = cal(b/k, d/k) - cal((a-1)/k, d/k) - cal(b/k, (c-1)/k) + cal((a-1)/k, (c-1)/k);
    printf("%lld\n", ans);
}

在附上同时处理欧拉函数的:

typedef long long ll;
const int maxn = 1e5+5;
bool vis[maxn];
int pri[maxn], mu[maxn], phi[maxn], sum[maxn];
void init() {   // 预处理莫比乌斯(前缀), 欧拉, 以及素数
    Fill(vis, true); vis[1] = false;
    mu[1] = 1; int cnt = 0; phi[1] = 1;
    for (int i = 2 ; i < maxn ;  i ++) {
        if (vis[i]) {
            pri[++cnt] = i;
            mu[i] = -1;
            phi[i] = i -1;
        }
        for (int j = 1 ; j <= cnt ; j ++) {
            if (i*pri[j] > maxn) break;
            vis[i * pri[j]] = false;
            if (i % pri[j]) {
                mu[i * pri[j]] = -mu[i];
                phi[i * pri[j]] = phi[i] * (pri[j] - 1);
            }
            else {
                phi[i * pri[j]] = phi[i] * pri[j];
                mu[i * pri[j]] = 0;
                break;
            }
        }
    }
    sum[0] = 0;
    for (int i = 1 ; i < maxn ; i ++) {
        sum[i] = sum[i-1] + mu[i];
    }
}

你可能感兴趣的:(原根/莫比乌斯学习)