BZOJ 3994. [SDOI2015]约数个数和

 

求 $$\sum_{i=1}^n\sum_{j=1}^md(ij)$$
$$d(ij)=\sum_{x|i}\sum_{y|j}[(x,y)=1]=\sum_{x|i}\sum_{y|j}\sum_{p|(x,y)}\mu(p)$$
$$=\sum_p \mu(p)\sum_{x|i}[d|x]\sum_{y|j}[d|y]=\sum_{p|i,p|j}\mu(p)d(\frac{i}{p})d(\frac{j}{p})$$
代回原式得
$$\sum_{i=1}^n\sum_{j=1}^m\sum_{p|i,p|j}\mu(p)d(\frac{i}{p})d(\frac{j}{p})=\sum_{p}\mu(p)\sum_{p|i}d(\frac{i}{p})\sum_{p|j}d(\frac{j}{p})$$
$$=\sum_{p}\mu(p)\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}d(i)\sum_{j=1}^{\lfloor \frac{m}{p} \rfloor}d(j)$$
令 $s(n)=\sum_{i=1}^n d(i)$
原式为$$\sum_{p}\mu(p)s(\lfloor \frac{n}{p} \rfloor)s(\lfloor \frac{m}{p} \rfloor)$$

#include <bits/stdc++.h>

const int N = 5e4 + 7;
int mu[N], prime[N], prin, d[N], t[N];
bool vis[N];

void init(int n) {
    mu[1] = d[1] = t[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!vis[i]) {
            prime[++prin] = i;
            d[i] = 2;
            t[i] = 1;
            mu[i] = -1;
        }
        for (int j = 1; j <= prin && i * prime[j] < N; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                t[i * prime[j]] = t[i] + 1;
                mu[i * prime[j]] = 0;
                d[i * prime[j]] = d[i] / (t[i] + 1) * (t[i] + 2);
                break;
            }
            d[i * prime[j]] = d[i] * 2;
            t[i * prime[j]] = 1;
            mu[i * prime[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= n; i++)
        mu[i] += mu[i - 1], d[i] += d[i - 1];
}

#define ll long long

ll solve(int n, int m) {
    ll ans = 0;
    if (n > m) std::swap(n, m);
    for (int i = 1, j; i <= n; i = j + 1) {
        j = std::min(n / (n / i), m / (m / i));
        ans += 1LL * (mu[j] - mu[i - 1]) * 1LL * d[n / i] * d[m / i];
    }
    return ans;
}

int main() {
    init(N - 1);
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        printf("%lld\n", solve(n, m));
    }
    return 0;
}
View Code

 

posted @ 2020-02-02 11:57  Mrzdtz220  阅读(130)  评论(0编辑  收藏  举报