Chương 7·Bài 70

Möbius Function

Đếm cặp, tập con hay dãy có ước chung lớn nhất bằng 1 thì khó, nhưng đếm những cái cùng chia hết cho dd lại dễ: chỉ cần biết có bao nhiêu phần tử là bội của dd. Hàm Möbius μ\mu là trọng số để chuyển từ cái dễ sang cái khó: ∑d∣nμ(d)\sum_{d \mid n} \mu(d) bằng 1 khi n=1n = 1 và bằng 0 khi n>1n > 1, nên cộng “số chia hết cho dd” với trọng số μ(d)\mu(d) giữ lại đúng các đối tượng có gcd bằng 1. Kèm với chia khối theo thương ⌊n/d⌋\lfloor n/d \rfloor, các tổng này chạy trong O(n)O(\sqrt n) mỗi truy vấn.

Hàm Möbius và sàng tuyến tính

μ(1)=1\mu(1) = 1; μ(n)=0\mu(n) = 0 nếu nn chia hết cho bình phương một số nguyên tố; ngược lại μ(n)=(−1)k\mu(n) = (-1)^k với kk là số thừa số nguyên tố. Với n>1n > 1 có k≥1k \ge 1 thừa số nguyên tố phân biệt, các ước không chứa bình phương của nó là các tập con của kk thừa số, nên ∑d∣nμ(d)=∑j(kj)(−1)j=0\sum_{d \mid n} \mu(d) = \sum_j \binom{k}{j} (-1)^j = 0. Đây là toàn bộ bí mật: biểu thức [gcd⁡=1][\gcd = 1] thay được bằng ∑d∣gcd⁡μ(d)\sum_{d \mid \gcd} \mu(d), rồi đổi thứ tự tổng.

Sàng tuyến tính tính μ\mu cho mọi số tới NN trong O(N)O(N): mỗi hợp số bị đánh dấu đúng một lần bởi thừa số nguyên tố nhỏ nhất. Khi xét ii và số nguyên tố p≤p \le ước nguyên tố nhỏ nhất của ii: nếu p∣ip \mid i thì μ(ip)=0\mu(ip) = 0 và dừng; ngược lại μ(ip)=−μ(i)\mu(ip) = -\mu(i).

Ví dụ đầu: số không chứa bình phương tới NN là ∑dμ(d)⌊N/d2⌋\sum_{d} \mu(d) \lfloor N / d^2 \rfloor, với dd chạy tới N\sqrt N: mỗi số xx được đếm với trọng số ∑d2∣xμ(d)\sum_{d^2 \mid x} \mu(d), bằng 1 đúng khi xx không chia hết cho bình phương nào.

Bảng μ từ 1 tới 48. Bấm một số: các ước của nó sáng lên, tổng μ trên các ước bằng 0 trừ khi số đó là 1.

Ví dụĐếm Số Không Chứa Bình Phương

Đề. T≤100T \le 100 truy vấn, mỗi truy vấn N≤1014N \le 10^{14}. Đếm số không chứa bình phương trong [1,N][1, N].

Lời giải. Số không chứa bình phương tới NN là ∑d≤Nμ(d)⌊N/d2⌋\sum_{d \le \sqrt N} \mu(d) \lfloor N / d^2 \rfloor, nên cần μ\mu tới 1014=107\sqrt{10^{14}} = 10^7. Duyệt 10710^7 số hạng cho mỗi truy vấn là 10910^9 phép với 100 truy vấn, quá chậm. Nhưng thương q=⌊N/d2⌋q = \lfloor N/d^2 \rfloor chỉ có O(N1/3)O(N^{1/3}) giá trị khác nhau, và mọi dd từ dd tới e=⌊N/q⌋e = \lfloor \sqrt{N/q} \rfloor cho cùng qq: gom cả khối, cộng q⋅∑d′=deμ(d′)q \cdot \sum_{d'=d}^{e} \mu(d') lấy từ tổng tiền tố.

Bước 1: sàng tuyến tính μ\mu. Mỗi hợp số i⋅pi \cdot p được đánh dấu đúng một lần, bởi pp là ước nguyên tố nhỏ nhất của nó. Khi i % p == 0 thì p2∣ipp^2 \mid ip, μ=0\mu = 0, và dừng: các số nguyên tố lớn hơn không còn là ước nhỏ nhất của i⋅p′i \cdot p'. Ngược lại ipip có thêm một thừa số nguyên tố mới, μ(ip)=−μ(i)\mu(ip) = -\mu(i). mu lưu bằng signed char, pre bằng int, để hai mảng 10710^7 phần tử chỉ tốn khoảng 50 MB.

C++
for (int i = 2; i < M; i++) {
    if (!comp[i]) primes.push_back(i), mu[i] = -1;
    for (int p : primes) {
        if ((ll)i * p >= M) break;
        comp[i * p] = 1;
        if (i % p == 0) {
            mu[i * p] = 0;
            break;
        }
        mu[i * p] = -mu[i];
    }
}

Bước 2: chia khối theo thương. e = isqrt(n / q) là dd lớn nhất còn cho ⌊N/d2⌋=q\lfloor N / d^2 \rfloor = q. isqrt là căn nguyên chính xác như bài 66, vì sqrtl có thể lệch 1 ở gần số chính phương.

C++
for (ll d = 1; d <= lim;) {
    ll q = n / (d * d), e = isqrt(n / q);
    ans += q * (pre[e] - pre[d - 1]);
    d = e + 1;
}
Code đầy đủ
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int M = 1e7 + 5;
int pre[M];
signed char mu[M];
vector<int> primes;
bool comp[M];

ll isqrt(ll x) {
    ll r = sqrtl((long double)x);
    while (r * r > x) r--;
    while ((r + 1) * (r + 1) <= x) r++;
    return r;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    mu[1] = 1;
    for (int i = 2; i < M; i++) {
        if (!comp[i]) primes.push_back(i), mu[i] = -1;
        for (int p : primes) {
            if ((ll)i * p >= M) break;
            comp[i * p] = 1;
            if (i % p == 0) {
                mu[i * p] = 0;
                break;
            }
            mu[i * p] = -mu[i];
        }
    }
    for (int i = 1; i < M; i++) pre[i] = pre[i - 1] + mu[i];
    int T;
    cin >> T;
    while (T--) {
        ll n;
        cin >> n;
        ll lim = isqrt(n), ans = 0;
        for (ll d = 1; d <= lim;) {
            ll q = n / (d * d), e = isqrt(n / q);
            ans += q * (pre[e] - pre[d - 1]);
            d = e + 1;
        }
        cout << ans << '\n';
    }
}
4
1
10
30
100

Sàng O(N)O(\sqrt{N}) một lần; mỗi truy vấn O(N1/3)O(N^{1/3}) khối, khoảng vài chục nghìn với N=1014N = 10^{14}.

Đếm theo bội

Gọi cdc_d là số phần tử của dãy chia hết cho dd (tính bằng cách duyệt bội: với mỗi dd, cộng số lần xuất hiện của d,2d,3d,…d, 2d, 3d, \dots, tổng O(Vlog⁡V)O(V \log V)). Số cặp có gcd chia hết cho dd là (cd2)\binom{c_d}{2}, số tập con khác rỗng là 2cd−12^{c_d} - 1. Thay [gcd⁡=1]=∑d∣gcd⁡μ(d)[\gcd = 1] = \sum_{d \mid \gcd} \mu(d):

#{cặp coˊ gcd 1}=∑dμ(d)(cd2),#{tập con coˊ gcd 1}=∑dμ(d) (2cd−1).\#\{\text{cặp có gcd } 1\} = \sum_{d} \mu(d) \binom{c_d}{2}, \qquad \#\{\text{tập con có gcd } 1\} = \sum_d \mu(d)\,(2^{c_d} - 1).

Cùng khuôn mẫu cho bộ ba, bộ bốn ((cd4)\binom{c_d}{4}), dãy có thứ tự trong hộp (⌊n/d⌋k\lfloor n/d \rfloor^k), điểm nhìn thấy trên lưới.

Hỏi nhanh

Dãy 2,3,42, 3, 4. Theo công thức ∑dμ(d)(2cd−1)\sum_d \mu(d)(2^{c_d} - 1), có bao nhiêu tập con có gcd bằng 1?

Ví dụNhững Cặp Không Chung Ước

Đề. Dãy n≤105n \le 10^5 số tới 10610^6. Đếm cặp chỉ số có hai giá trị nguyên tố cùng nhau.

Lời giải. Số cặp chỉ số có gcd chia hết cho dd là (cd2)\binom{c_d}{2}, với cdc_d là số phần tử chia hết cho dd. Thay điều kiện [gcd⁡=1][\gcd = 1] bằng ∑d∣gcd⁡μ(d)\sum_{d \mid \gcd} \mu(d) rồi đổi thứ tự tổng: số cặp nguyên tố cùng nhau là ∑dμ(d)(cd2)\sum_d \mu(d) \binom{c_d}{2}. Sàng tuyến tính μ\mu tới 10610^6 như ví dụ trước.

Bước 1: cdc_d qua tần suất. freq[x] là số lần giá trị xx xuất hiện; c cộng freq ở d,2d,3d,…d, 2d, 3d, \dots. Bỏ qua dd có μ(d)=0\mu(d) = 0, đỡ khoảng 40% số vòng. c * (c - 1) / 2 tới 5⋅1095 \cdot 10^9, phải là long long.

C++
for (int d = 1; d < V; d++) {
    if (!mu[d]) continue;
    ll c = 0;
    for (int k = d; k < V; k += d) c += freq[k];
    ans += mu[d] * c * (c - 1) / 2;
}
Code đầy đủ
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int V = 1e6 + 5;
int n, mu[V], freq[V];
bool comp[V];
vector<int> primes;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    mu[1] = 1;
    for (int i = 2; i < V; i++) {
        if (!comp[i]) primes.push_back(i), mu[i] = -1;
        for (int p : primes) {
            if ((ll)i * p >= V) break;
            comp[i * p] = 1;
            if (i % p == 0) {
                mu[i * p] = 0;
                break;
            }
            mu[i * p] = -mu[i];
        }
    }
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        freq[x]++;
    }
    ll ans = 0;
    for (int d = 1; d < V; d++) {
        if (!mu[d]) continue;
        ll c = 0;
        for (int k = d; k < V; k += d) c += freq[k];
        ans += mu[d] * c * (c - 1) / 2;
    }
    cout << ans << '\n';
}
6
2 3 4 9 10 25

V(1+12+13+… )=O(Vlog⁡V)V (1 + \frac12 + \frac13 + \dots) = O(V \log V).

Ví dụTập Con Có GCD Bằng Một

Đề. Dãy n≤105n \le 10^5 số tới 10510^5. Đếm tập chỉ số khác rỗng có gcd bằng 1, theo mô-đun 109+710^9 + 7.

Lời giải. Cùng khuôn với ví dụ trước: số tập chỉ số khác rỗng mà mọi phần tử chia hết cho dd là 2cd−12^{c_d} - 1, nên đáp án là ∑dμ(d)(2cd−1)\sum_d \mu(d)(2^{c_d} - 1) theo mô-đun. cd≤nc_d \le n nên lũy thừa của 2 tính sẵn tới nn.

C++
pw[0] = 1;
for (int i = 1; i <= n; i++) pw[i] = pw[i - 1] * 2 % MOD;

Số hạng có thể âm khi μ(d)=−1\mu(d) = -1, nên cộng thêm MOD trước khi lấy dư.

C++
ans = (ans + mu[d] * (pw[c] - 1) + MOD) % MOD;
Code đầy đủ
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int V = 1e5 + 5;
const ll MOD = 1e9 + 7;
int n, mu[V], freq[V];
ll pw[V];
bool comp[V];
vector<int> primes;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    mu[1] = 1;
    for (int i = 2; i < V; i++) {
        if (!comp[i]) primes.push_back(i), mu[i] = -1;
        for (int p : primes) {
            if ((ll)i * p >= V) break;
            comp[i * p] = 1;
            if (i % p == 0) {
                mu[i * p] = 0;
                break;
            }
            mu[i * p] = -mu[i];
        }
    }
    cin >> n;
    pw[0] = 1;
    for (int i = 1; i <= n; i++) pw[i] = pw[i - 1] * 2 % MOD;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        freq[x]++;
    }
    ll ans = 0;
    for (int d = 1; d < V; d++) {
        if (!mu[d]) continue;
        int c = 0;
        for (int k = d; k < V; k += d) c += freq[k];
        ans = (ans + mu[d] * (pw[c] - 1) + MOD) % MOD;
    }
    cout << ans << '\n';
}
3
2 3 4

O(Vlog⁡V)O(V \log V).

Gcd đúng bằng g: trừ từ trên xuống

Đảo Möbius cũng có dạng trừ dần: gọi F(g)F(g) là số đối tượng có gcd chia hết cho gg (dễ tính), E(g)E(g) là số có gcd đúng bằng gg. Vì F(g)=∑k≥1E(kg)F(g) = \sum_{k \ge 1} E(kg), duyệt gg từ lớn xuống nhỏ:

E(g)=F(g)−∑k≥2E(kg).E(g) = F(g) - \sum_{k \ge 2} E(kg).

Tổng ∑g∑k\sum_g \sum_k là O(Klog⁡K)O(K \log K), không cần đến μ\mu. Cách này hợp khi cần E(g)E(g) cho mọi gg, như tính tổng gcd: ∑gg⋅E(g)\sum_g g \cdot E(g).

Duyệt g từ lớn xuống: E(g) lấy F(g) trừ đi E của mọi bội thật sự (xanh dương) đã tính xong.

Ví dụTổng GCD Của Mọi Dãy

Đề. Mọi dãy dài N≤105N \le 10^5 với phần tử trong [1,K][1, K], K≤105K \le 10^5. Tính tổng gcd của chúng theo mô-đun 109+710^9 + 7.

Lời giải. Gọi F(g)F(g) là số dãy có gcd chia hết cho gg: mọi phần tử là bội của gg, mỗi phần tử có ⌊K/g⌋\lfloor K/g \rfloor lựa chọn, nên F(g)=⌊K/g⌋NF(g) = \lfloor K/g \rfloor^N. E(g)E(g) là số dãy có gcd đúng bằng gg. Vì F(g)=∑k≥1E(kg)F(g) = \sum_{k \ge 1} E(kg), duyệt gg từ KK xuống 1 thì E(g)=F(g)−∑k≥2E(kg)E(g) = F(g) - \sum_{k \ge 2} E(kg), với mọi E(kg)E(kg) đã tính xong. Đáp án là ∑gg⋅E(g)\sum_g g \cdot E(g).

C++
for (ll g = k; g >= 1; g--) {
    E[g] = power(k / g, n);
    for (ll m = 2 * g; m <= k; m += g) E[g] = (E[g] - E[m] + MOD) % MOD;
    ans = (ans + g * E[g]) % MOD;
}

Kiểm với mẫu: N=2N = 2, K=3K = 3 có 9 dãy; E(3)=1E(3) = 1, E(2)=1E(2) = 1, E(1)=9−1−1=7E(1) = 9 - 1 - 1 = 7, tổng 7+2+3=127 + 2 + 3 = 12.

Code đầy đủ
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const ll MOD = 1e9 + 7;
ll n, k, E[100005];

ll power(ll a, ll b) {
    ll r = 1;
    a %= MOD;
    while (b) {
        if (b & 1) r = r * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return r;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> k;
    ll ans = 0;
    for (ll g = k; g >= 1; g--) {
        E[g] = power(k / g, n);
        for (ll m = 2 * g; m <= k; m += g) E[g] = (E[g] - E[m] + MOD) % MOD;
        ans = (ans + g * E[g]) % MOD;
    }
    cout << ans << '\n';
}
2 3

Vòng trừ bội O(Klog⁡K)O(K \log K), lũy thừa O(Klog⁡N)O(K \log N).

Chia khối theo thương

Số cặp x≤nx \le n, y≤my \le m có gcd⁡(x,y)=1\gcd(x, y) = 1 là ∑d≥1μ(d)⌊n/d⌋⌊m/d⌋\sum_{d \ge 1} \mu(d) \lfloor n/d \rfloor \lfloor m/d \rfloor. Với nhiều truy vấn, O(n)O(n) mỗi truy vấn là quá chậm, nhưng ⌊n/d⌋\lfloor n/d \rfloor chỉ có O(n)O(\sqrt n) giá trị: với dd hiện tại, mọi d′d' tới e=min⁡(n/⌊n/d⌋,m/⌊m/d⌋)e = \min(n / \lfloor n/d \rfloor, m / \lfloor m/d \rfloor) cho cùng cặp thương, nên cộng cả khối bằng tổng tiền tố của μ\mu trên [d,e][d, e]. Mỗi truy vấn O(n+m)O(\sqrt n + \sqrt m).

Cột trên là ⌊n/d⌋, cột dưới là ⌊m/d⌋; mỗi dải màu là một khối mà cả hai thương cùng không đổi.

Gcd đúng bằng kk trong hình chữ nhật [1,n]×[1,m][1, n] \times [1, m]: chia hai cạnh cho kk rồi đếm cặp nguyên tố cùng nhau. Đoạn [a,b]×[c,d][a, b] \times [c, d] thì bao hàm loại trừ bốn góc.

Hỏi nhanh

Với n=100n = 100, ⌊100/d⌋\lfloor 100/d \rfloor nhận bao nhiêu giá trị khác nhau khi d=1..100d = 1..100?

Ví dụTruy Vấn Ước Chung Trên Hai Đoạn

Đề. T≤5⋅104T \le 5 \cdot 10^4 truy vấn a,b,c,d,ka, b, c, d, k (tới 5⋅1045 \cdot 10^4). Đếm cặp x∈[a,b]x \in [a, b], y∈[c,d]y \in [c, d] có gcd⁡(x,y)=k\gcd(x, y) = k.

Lời giải. gcd⁡(x,y)=k\gcd(x, y) = k khi và chỉ khi x=kx′x = k x', y=ky′y = k y' với gcd⁡(x′,y′)=1\gcd(x', y') = 1. Vậy số cặp trong [1,n]×[1,m][1, n] \times [1, m] là f(⌊n/k⌋,⌊m/k⌋)f(\lfloor n/k \rfloor, \lfloor m/k \rfloor), với f(n,m)=∑dμ(d)⌊n/d⌋⌊m/d⌋f(n, m) = \sum_d \mu(d) \lfloor n/d \rfloor \lfloor m/d \rfloor đếm cặp nguyên tố cùng nhau. Đoạn [a,b]×[c,d][a, b] \times [c, d] lấy bằng bao hàm loại trừ bốn góc.

Bước 1: ff bằng chia khối. Đổi chỗ để n≤mn \le m, vì khi d>nd > n thì ⌊n/d⌋=0\lfloor n/d \rfloor = 0. e là dd lớn nhất mà cả hai thương không đổi; cả khối cộng một lần bằng pre[e] - pre[d - 1].

C++
ll f(ll n, ll m) {
    if (n > m) swap(n, m);
    ll res = 0;
    for (ll d = 1; d <= n;) {
        ll e = min(n / (n / d), m / (m / d));
        res += (ll)(pre[e] - pre[d - 1]) * (n / d) * (m / d);
        d = e + 1;
    }
    return res;
}

Bước 2: bốn góc. (a - 1) / k với a=1a = 1 bằng 0, và f(0, ·) = 0 vì vòng không chạy.

C++
ll ans = f(b / k, d / k) - f((a - 1) / k, d / k) - f(b / k, (c - 1) / k) + f((a - 1) / k, (c - 1) / k);
Code đầy đủ
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int V = 5e4 + 5;
int mu[V], pre[V];
bool comp[V];
vector<int> primes;

ll f(ll n, ll m) {
    if (n > m) swap(n, m);
    ll res = 0;
    for (ll d = 1; d <= n;) {
        ll e = min(n / (n / d), m / (m / d));
        res += (ll)(pre[e] - pre[d - 1]) * (n / d) * (m / d);
        d = e + 1;
    }
    return res;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    mu[1] = 1;
    for (int i = 2; i < V; i++) {
        if (!comp[i]) primes.push_back(i), mu[i] = -1;
        for (int p : primes) {
            if ((ll)i * p >= V) break;
            comp[i * p] = 1;
            if (i % p == 0) {
                mu[i * p] = 0;
                break;
            }
            mu[i * p] = -mu[i];
        }
    }
    for (int i = 1; i < V; i++) pre[i] = pre[i - 1] + mu[i];
    int T;
    cin >> T;
    while (T--) {
        ll a, b, c, d, k;
        cin >> a >> b >> c >> d >> k;
        ll ans = f(b / k, d / k) - f((a - 1) / k, d / k) - f(b / k, (c - 1) / k) + f((a - 1) / k, (c - 1) / k);
        cout << ans << '\n';
    }
}
3
2 4 3 5 1
2 4 3 5 2
4 6 6 8 2

Mỗi truy vấn bốn lần f với khoảng 25⋅104≈4502\sqrt{5 \cdot 10^4} \approx 450 khối, tổng khoảng 10810^8 phép nhẹ.

Khi đi thi

  • Điều kiện “gcd bằng 1” hay “nguyên tố cùng nhau”: thay bằng ∑d∣gcd⁡μ(d)\sum_{d \mid \gcd} \mu(d), đổi thứ tự tổng, đếm theo bội cdc_d. Gcd đúng bằng gg cho mọi gg: trừ từ trên xuống.
  • Tổng có dạng ∑dμ(d)⌊n/d⌋⌊m/d⌋\sum_d \mu(d) \lfloor n/d \rfloor \lfloor m/d \rfloor với nhiều truy vấn: tổng tiền tố μ\mu và chia khối theo thương.
  • Sàng tuyến tính tính μ\mu, φ\varphi, ước nguyên tố nhỏ nhất cùng lúc trong O(N)O(N).

Tóm tắt

  • ∑d∣nμ(d)=[n=1]\sum_{d \mid n} \mu(d) = [n = 1]; μ\mu bằng 0 với số chứa bình phương, (−1)k(-1)^k với tích kk số nguyên tố khác nhau.
  • Số đối tượng có gcd bằng 1 là ∑dμ(d)⋅(soˆˊ đoˆˊi tượng toaˋn bội của d)\sum_d \mu(d) \cdot (\text{số đối tượng toàn bội của } d).
  • E(g)=F(g)−∑k≥2E(kg)E(g) = F(g) - \sum_{k \ge 2} E(kg) cho gcd đúng bằng gg, O(Klog⁡K)O(K \log K).
  • ⌊n/d⌋\lfloor n/d \rfloor có O(n)O(\sqrt n) giá trị; gom khối để mỗi truy vấn O(n)O(\sqrt n).

Bài tập

1
Dãy Dương Có Tổng Cố Địnhcanuc80k7003yy phải chia hết cho xx; với m=y/xm = y/x, số dãy tổng mm có gcd 1 là ∑d∣mμ(d) 2m/d−1\sum_{d \mid m} \mu(d)\, 2^{m/d - 1}.
LQDOJ
2
Phân Hoạch Có Thứ Tựcanuc80k7004Số bộ ff số dương tổng nn là (n−1f−1)\binom{n-1}{f-1}; gcd bằng 1 thì ∑d∣nμ(d)(n/d−1f−1)\sum_{d \mid n} \mu(d) \binom{n/d - 1}{f - 1}.
LQDOJ
3
Cặp Có Ước Chung Đúng Dcanuc80k7006Chia hai cạnh cho DD rồi đếm cặp nguyên tố cùng nhau bằng chia khối như ví dụ cuối.
LQDOJ
4
Chọn Bốn Số Có GCD Bằng Mộtcanuc80k7007Bộ bốn chỉ số có gcd chia hết cho dd: (cd4)\binom{c_d}{4}; cộng với trọng số μ(d)\mu(d).
LQDOJ
5
Điểm Nguyên Nhìn Thấy Trong Khối Lập Phươngcanuc80k7008Điểm nhìn thấy có gcd ba tọa độ bằng 1: ∑dμ(d)((⌊N/d⌋+1)3−1)\sum_d \mu(d)\big((\lfloor N/d \rfloor + 1)^3 - 1\big).
LQDOJ
6
Các Vị Trí Đầu Tiacanuc80k7009N=1N = 1 thì 0; ngược lại điểm nhìn thấy có tọa độ nguyên tố cùng nhau, đếm bằng μ\mu hay tổng φ\varphi rồi cộng hai trục.
LQDOJ
7
Cặp Không Chia Hết Một Phíacanuc80k7010Đếm cặp có gcd lớn hơn 1 bằng μ\mu, rồi trừ các cặp mà một số là bội của số kia (khi đó x/gx/g hay y/gy/g bằng 1).
LQDOJ
8
Tổng Trọng Số Các Tập Concanuc80k7011Với mỗi dd, tổng kích thước mọi tập con toàn bội của dd là cd2cd−1c_d 2^{c_d - 1}; trừ từ trên xuống để có gcd đúng bằng dd, nhân dd.
LQDOJ
9
Bật Tắt Các Chỉ Số Nguyên Tố Cùng Nhaucanuc80k7012Khi bật hay tắt xx, số chỉ số đang bật nguyên tố cùng nhau với nó là ∑d∣axμ(d) cntd\sum_{d \mid a_x} \mu(d)\, cnt_d; cập nhật cntcnt trên các ước không chứa bình phương.
LQDOJ
10
Các Cặp Có Ước Chung Lớn Hơn Mộtcanuc80k7016Lấy tổng số cặp x≤yx \le y trừ số cặp nguyên tố cùng nhau, tức trừ tổng φ\varphi.
LQDOJ
11
Ước Chung Là Số Nguyên Tốcanuc80k7017∑p∑dμ(d)⌊Npd⌋⌊Mpd⌋\sum_p \sum_d \mu(d) \lfloor \frac{N}{pd} \rfloor \lfloor \frac{M}{pd} \rfloor; gộp T=pdT = pd, tính sẵn g(T)=∑p∣Tμ(T/p)g(T) = \sum_{p \mid T} \mu(T/p) và chia khối.
LQDOJ
12
Số Không Chứa Bình Phương Thứ Kcanuc80k7018Chặt nhị phân xx nhỏ nhất có số không chứa bình phương tới xx bằng KK, đếm như ví dụ đầu.
LQDOJ
13
Tổng Bội Chung Nhỏ Nhất Theo Cặpcanuc80k7020lcm⁡=aiaj/gcd⁡\operatorname{lcm} = a_i a_j / \gcd; viết 1/gcd⁡1/\gcd thành tổng theo ước bằng Möbius và cộng theo bội.
LQDOJ
14
Tập Con Ngắn Nhất Có GCD Bằng Mộtcanuc80k7023Đáp án không quá 7; với mỗi kk đếm số tập kk phần tử có gcd 1 bằng ∑dμ(d)(cdk)\sum_d \mu(d)\binom{c_d}{k}, lấy kk nhỏ nhất cho kết quả dương.
LQDOJ
15
Tổng GCD Trên Hình Vuông Sốcanuc80k7024gcd⁡(i,j)=∑d∣gcd⁡φ(d)\gcd(i, j) = \sum_{d \mid \gcd} \varphi(d) nên tổng là ∑dφ(d)⌊N/d⌋2\sum_d \varphi(d) \lfloor N/d \rfloor^2.
LQDOJ

Đọc thêm

  • Hàm MobiusVNOI WikiĐịnh nghĩa, đảo Möbius và bài tập bằng tiếng Việt.
  • 莫比乌斯反演OI WikiĐảo Möbius, chia khối và nhiều bài mẫu.
  • Linear Sievecp-algorithmsSàng O(N)O(N) dùng để tính các hàm nhân tính.