BZOJ 3512. DZY Loves Math IV

 

因为 $n$ 比较小,所以可以对每一个 $n$ 求一遍 $\sum \limits_{i=1}^m \varphi(ni)$,然后加起来。

$S(n,m)=\sum\limits_{i=1}^m\varphi(ni)$,那么答案就是 $\sum\limits_{i=1}^n S(i,m)$

首先看 $\varphi(ni)$ 怎么求。

当 $|\mu(n)|=1$ 时,$\varphi(ni)=\varphi(\dfrac{n}{d}i)d=\varphi(\dfrac{n}{d})\varphi(i)d=\varphi(\dfrac{n}{d})\varphi(i)\sum\limits_{d'|d}\varphi(\dfrac{d}{d'})=\varphi(i)\sum \limits_{d'|d}\varphi(\dfrac{n}{d'})$

其中 $d = (n,i)$,上述推导根据积性函数的性质以及 $\varphi(n)=n\prod \limits_{p|n}(1-\dfrac{1}{p})$ 得到

那么 $$\begin{aligned}&S(n,m) \\=&\sum_{i=1}^m\varphi(ni)\\=&\sum_{i=1}^m\varphi(i)\sum_{d|(n,i)}\varphi(\frac{n}{d})\\=&\sum_{d|n}\varphi(\frac{n}{d})\sum_{d|i}\varphi(i)\\=&\sum_{d|n}\varphi(\frac{n}{d})\sum_{i=1}^{\lfloor \frac{m}{d} \rfloor}\varphi(id)\\=&\sum_{d|n}\varphi(\frac{n}{d})S(d,\lfloor \frac{m}{d} \rfloor)\end{aligned}$$

当 $n=1$ 时就是求 $\varphi$ 的前缀和,杜教筛解决。

当 $\mu(n)=0$ 时,$n=\prod\limits_{p_i | n}p_i^{c_i}$,$k=\prod\limits_{p_i | n}p_i$,那么 $S(n,m)=\dfrac{nS(k, m)}{k}$

#include <bits/stdc++.h>
#define pii pair<int, int>

const int N = 1e6 + 7;
const int MOD = 1e9 + 7;

void M(int &a) {
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
}

int prime[N], prin, mu[N], phi[N], mx[N], sum[N];

void init() {
    static bool vis[N];
    mu[1] = phi[1] = 1;
    for (int i = 2; i < N; i++) {
        if (!vis[i]) prime[++prin] = i, mu[i] = -1, phi[i] = i - 1, mx[i] = i;
        for (int j = 1; j <= prin && i * prime[j] < N; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = prime[j] * phi[i];
                mx[i * prime[j]] = mx[i];
                break;
            }
            phi[i * prime[j]] = phi[i] * phi[prime[j]];
            mu[i * prime[j]] = -mu[i];
            mx[i * prime[j]] = mx[i] * prime[j];
        }
    }
    for (int i = 1; i < N; i++)
        M(sum[i] = sum[i - 1] + phi[i]);
}

struct Hash {
    static const int mod = 1e6 + 7;
    int head[mod + 5], cnt;
    struct E {
        std::pii x;
        int ans, ne;
    } e[mod + 5];
    inline int getid(const std::pii &x) {
        return (1LL * x.first * MOD + x.second) % mod;
    }
    void insert(const std::pii &x, int ans) {
        int u = getid(x);
        e[++cnt].x = x; e[cnt].ans = ans; e[cnt].ne = head[u]; head[u] = cnt;
    }
    int query(const std::pii &x) {
        int u = getid(x);
        for (int i = head[u]; i; i = e[i].ne) 
            if (e[i].x == x) return e[i].ans;
        return -1;
    }
} H;

int sum1(int n) {
    return 1LL * n * (n + 1) / 2 % MOD;
}

int S(int n, int m) {
    if (!n || !m) return 0;
    if (n == 1 && m < N) return sum[m];
    int ans = H.query(std::pii(n, m));
    if (~ans) return ans;
    ans = 0;
    if (n == 1) {
        ans = sum1(m);
        for (int i = 2, j; i <= m; i = j + 1) {
            j = m / (m / i);
            M(ans -= 1LL * (j - i + 1) * S(n, m / i));
        }
    } else if (mu[n] == 0) {
        M(ans = 1LL * n / mx[n] * S(mx[n], m) % MOD);
    } else {
        for (int d = 1; d * d <= n; d++) {
            if (n % d) continue;
            M(ans += 1LL * phi[n / d] * S(d, m / d) % MOD);
            if (d * d < n)
                M(ans += 1LL * phi[d] * S(n / d, m / (n / d)) % MOD);
        }
    }
    H.insert(std::pii(n, m), ans);
    return ans;
}

int main() {
    init();
    int n, m;
    scanf("%d%d", &n, &m);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        M(ans += S(i, m));
    }
    printf("%d\n", ans);
    return 0;
}
View Code

 

posted @ 2020-02-03 16:03  Mrzdtz220  阅读(87)  评论(0编辑  收藏  举报