计蒜客 tsy's number

 

链接

$$\begin{aligned} & \sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{k=1}^{n} j k^{2} \varphi(\gcd(i, j, k))\\=& \sum_{d=1}^n d^{3} \varphi(d) \sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{k=1}^{\left\lfloor\frac{n}{d}\right\rfloor}jk^2[\gcd(i,j,k)=1]\\=& \sum_{d=1}^n d^{3} \varphi(d) \sum_{t=1}^{\lfloor \frac{n}{d} \rfloor} t^{3} \mu(t) \sum_{i=1}^{\left\lfloor\frac{n}{d t}\right\rfloor} \sum_{j=1}^{\left\lfloor\frac{n}{d t}\right\rfloor} \sum_{k=1}^{\left\lfloor\frac{n}{d t}\right\rfloor} j k^{2}\\=& \sum_{T}S_0(\lfloor \dfrac{n}{T} \rfloor)S_1(\lfloor \dfrac{n}{T} \rfloor)S_2(\lfloor \dfrac{n}{T} \rfloor) T^{3} \sum_{d | T} \varphi(d) \mu\left(\frac{T}{d}\right) \end{aligned}$$

其中 $S_k(n)=\sum \limits_{i=1}^n i^k$

先把 $f(n)=\sum\limits_{d|n}\varphi(d)\mu(\dfrac{n}{d})$ 线性筛筛出来,然后再求出 $g(n)=n^3f(n)$ 的前缀和即可。

#include <bits/stdc++.h>

const int N = 1e7;

struct P {
    int m, t, mp;
} p[N + 7];
int prime[N + 7], prin;
unsigned f[N + 7];
bool vis[N + 7];

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

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

unsigned sum2(int n) {
    return 1ull * n * (n + 1) % (6ull << 30) * (2 * n + 1) % (6ull << 30) / 6;
}

int main() {
    init();
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        unsigned ans = 0;
        for (int i = 1, j; i <= n; i = j + 1) {
            j = n / (n / i);
            ans += (f[j] - f[i - 1]) * (n / i) * sum1(n / i) * sum2(n / i);
        }
        printf("%u\n", ans & ((1 << 30) - 1));
    }
    return 0;
}
View Code

 

posted @ 2020-02-02 17:15  Mrzdtz220  阅读(111)  评论(0编辑  收藏  举报