51nod 1220 约数之和

Posted mrzdtz220

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1220 约数之和相关的知识,希望对你有一定的参考价值。

 

$sigma_{0}(ij)=sumlimits_{x|i}sumlimits_{y|j}[xot y]$
$sigma_{1}(ij)=sumlimits_{x|i}sumlimits_{y|j}dfrac{xj}{y}[xot y]$
所以 $$egin{aligned}&sum_{i=1}^nsum_{j=1}^n sigma_{1}(ij)=& sum_{i=1}^nsum_{j=1}^n sum_{x|i}sum_{y|j}dfrac{xj}{y}[xot y]=& sum_{d=1}^nmu(d)sum_{i=1}^nsum_{j=1}^nsum_{x|i}sum_{y|j}dfrac{xj}{y}[d|(x,y)]=&sum_{d=1}^nmu(d)sum_{d|x}sum_{d|y} frac{x}{y}sum_{x|i}sum_{y|j}j =& sum_{d=1}^n mu(d)sum_{d|x}sum_{d|y}frac{x}{y}s_0(lfloorfrac{n}{x} floor)ys_1(lfloorfrac{n}{y} floor)=& sum_{i=1}^n mu(d)dsum_{i=1}^{lfloor frac{n}{d} floor}is_0(lfloor frac{n}{id} floor) sum_{j=1}^{lfloor frac{n}{d} floor}s_1(lfloor frac{n}{jd} floor) end{aligned}$$
$sum limits_{i=1}^n ilfloor dfrac{n}{i} floor=sumlimits_{i=1}^n sigma_1(i)$
$sum limits_{i=1}^n s_1(lfloor dfrac{n}{i} floor)=sumlimits_{i=1}^n sumlimits_{j=1}^{lfloor frac{n}{i} floor}j=sum_{i=1}^n ilfloor dfrac{n}{i} floor$
二者等价
式子变成 $$sum_{i=1}^n mu(d)d left(sum_{i=1}^{lfloor frac{n}{d} floor}sigma_1(i) ight)^2$$
对于 $f(n)=nmu(n)$,有 $f * I = epsilon$,杜教筛之后的式子就是 $S(n)=1-sumlimits_{i=2}^n iS(lfloor dfrac{n}{i} floor)$
对于 $sigma_1$ 的前缀和,小范围预处理,大的用 $sumlimits_{i=1}^n sigma_1(i)=sum limits_{i=1}^n ilfloor dfrac{n}{i} floor$ 整除分块解决。

技术图片
#include <bits/stdc++.h>

const int N = 1e6 + 7;
const int MOD = 1000000007;
int mu[N], prime[N], prin, d[N], t[N];
bool vis[N];

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

int qp(int a, int b = MOD - 2) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = 1LL * ans * a % MOD;
        b >>= 1;
        a = 1LL * a * a % MOD;
    }
    return ans;
}

const int inv6 = qp(6);

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

std::unordered_map<int, int> muu, dd;

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

inline int sum1(int i, int j) {
    int ans;
    M(ans = sum1(j) - sum1(i - 1));
    return ans;
}

inline int sum2(int n) {
    return 1LL * n * (n + 1) % MOD * (2 * n + 1) % MOD * inv6 % MOD;
}

inline int sum2(int i, int j) {
    int ans = sum2(j) - sum2(i - 1);
    M(ans);
    return ans;
}

inline int Mu(int n) {
    if (n < N) return mu[n];
    if (muu.count(n)) return muu[n];
    int ans = 1;
    for (int i = 2, j; i <= n; i = j + 1) {
        j = n / (n / i);
        M(ans -= 1LL * sum1(i, j) * Mu(n / i) % MOD);
    }
    return muu[n] = ans;
}

inline int D(int n) {
    if (n < N) return d[n];
    if (dd.count(n)) return dd[n];
    int ans = 0;
    for (int i = 1, j; i <= n; i = j + 1) {
        j = n / (n / i);
        M(ans += 1LL * sum1(i, j) * (n / i) % MOD);
    }
    return dd[n] = ans;
}

int solve(int n) {
    int ans = 0;
    for (int i = 1, j; i <= n; i = j + 1) {
        j = n / (n / i);
        M(ans += 1LL * (Mu(j) - Mu(i - 1) + MOD) % MOD * D(n / i) % MOD * D(n / i) % MOD);
    }
    return ans;
}

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

 

以上是关于51nod 1220 约数之和的主要内容,如果未能解决你的问题,请参考以下文章

51nod1220约数之和

51nod1220 约数之和

51nod 1220 约数之和(杜教筛 + 推推推推推公式)

[51nod1040]最大公约数之和

[51Nod 1584] 加权约数和

51Nod 1237最大公约数之和 V3 莫比乌斯反演+杜教筛