[51Nod 1584] 加权约数和(约数和函数性质 + 莫比乌斯反演) | 错题本

文章目录

题目

[51Nod 1584] 加权约数和

分析

先把 max ⁡ { i , j } \max\{i, j\} max{i,j} 去掉:
原 式 = 2 ∑ i = 1 N ∑ j = 1 i i σ ( i j ) − ∑ i = 1 N i σ ( i 2 ) 原式=2\sum_{i = 1}^{N}\sum_{j = 1}^i i\sigma(ij)-\sum_{i = 1}^N i\sigma(i^2) =2i=1Nj=1iiσ(ij)i=1Niσ(i2)


推式子前先介绍约数和函数有一个重要性质(和约数个数一样可以转化为 gcd ⁡ \gcd gcd 问题): σ ( x y ) = ∑ i ∣ x ∑ j ∣ y i j [ gcd ⁡ ( i , y j ) = 1 ] = ∑ i ∣ x ∑ j ∣ y i y j [ gcd ⁡ ( i , j ) = 1 ] \begin{aligned}\sigma(xy)=&\sum_{i|x}\sum_{j|y}ij\left[\gcd\left(i, \frac{y}{j}\right)=1\right]\\=&\sum_{i| x}\sum_{j|y}i\frac{y}{j}[\gcd(i, j) = 1]\end{aligned} σ(xy)==ixjyij[gcd(i,jy)=1]ixjyijy[gcd(i,j)=1] 证明时考虑我们从 x x x 中枚举一个因数 i i i,从 y y y 中枚举一个因数 j j j,为了确保不算重,我们规定同一个质因子先从 y y y 中取到 j j j 里面,取完了再从 x x x 中取到 i i i 里面,这样的话所有 i j ij ij 都是 x y xy xy 的因数且不会算重。如何保证每个质因子都是先从 y y y 中取的呢?只需要看 y j \frac{y}{j} jy 中的某个质因数在不在 i i i 中,如果在,就意味着 y y y 中的这个质因数还没有取完,我们就从 x x x 中取了,这是不合法的,于是第一个等号得证,第二个等号就显然了。


先算第一个部分,代入上面的公式: ∑ i = 1 N ∑ j = 1 i i σ ( i j ) = ∑ i = 1 N ∑ j = 1 i i ∑ x ∣ i ∑ y ∣ j x j y [ gcd ⁡ ( x , y ) = 1 ] \begin{aligned}&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sigma(ij)\\=&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sum_{x|i}\sum_{y|j}x\frac{j}{y}[\gcd(x, y) = 1]\end{aligned} =i=1Nj=1iiσ(ij)i=1Nj=1iixiyjxyj[gcd(x,y)=1] 反演一下上式变为 ∑ i = 1 N ∑ j = 1 i i ∑ x ∣ i ∑ y ∣ j x j y ∑ d ∣ gcd ⁡ ( x , y ) μ ( d ) = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ d ∣ d x ∣ d i ∑ d ∣ d y ∣ d j d x d j d y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ x ∣ i ∑ y ∣ j d x d j d y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ x ∣ i d x ∑ y ∣ j j y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ d 2 i ∑ x ∣ i x ∑ j = 1 i ∑ y ∣ j y = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) ∑ j = 1 i σ ( j ) \begin{aligned}&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sum_{x|i}\sum_{y|j}x\frac{j}{y}\sum_{d|\gcd(x, y)} \mu(d)\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{d|dx|di}\sum_{d|dy|dj}dx\frac{dj}{dy}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{x|i}\sum_{y|j}dx\frac{dj}{dy}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{x|i}dx\sum_{y|j}\frac{j}{y}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}d^2i\sum_{x|i}x\sum_{j = 1}^{i}\sum_{y|j}y\\=&\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)\sum_{j = 1}^{i}\sigma(j)\end{aligned} =====i=1Nj=1iixiyjxyjdgcd(x,y)μ(d)d=1Nμ(d)i=1dNj=1ididdxdiddydjdxdydjd=1Nμ(d)i=1dNj=1idixiyjdxdydjd=1Nμ(d)i=1dNj=1idixidxyjyjd=1Nμ(d)i=1dNd2ixixj=1iyjyd=1Nμ(d)d2i=1dNiσ(i)j=1iσ(j) S ( x ) = ∑ i = 1 x σ ( i ) S(x)=\sum\limits_{i = 1}^x \sigma(i) S(x)=i=1xσ(i),别忘了还要最后乘个 2 2 2 2 ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) S ( i ) 2\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)S(i) 2d=1Nμ(d)d2i=1dNiσ(i)S(i) 再考虑第二部分,继续代入公式,差不多的方法: ∑ i = 1 N i σ ( i 2 ) = ∑ i = 1 N i ∑ x ∣ i ∑ y ∣ j x i y [ gcd ⁡ ( x , y ) = 1 ] = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ d i ∑ x ∣ i d x ∑ y ∣ i i y = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ 2 ( i ) \begin{aligned}&\sum_{i = 1}^N i\sigma(i^2)\\=&\sum_{i = 1}^Ni\sum_{x|i}\sum_{y|j}x\frac{i}{y}[\gcd(x,y)=1]\\=&\sum_{d=1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}di\sum_{x|i}dx\sum_{y|i}\frac{i}{y}\\=&\sum_{d=1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma^2(i)\end{aligned} ===i=1Niσ(i2)i=1Nixiyjxyi[gcd(x,y)=1]d=1Nμ(d)i=1dNdixidxyiyid=1Nμ(d)d2i=1dNiσ2(i) 两部分合起来: 原 式 = 2 ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) S ( i ) − ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ 2 ( i ) = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) ( 2 S ( i ) − σ ( i ) ) \begin{aligned} 原式=&2\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)S(i)-\sum_{d=1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma^2(i)\\=&\sum_{d=1}^N \mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)(2S(i)-\sigma(i))\end{aligned} ==2d=1Nμ(d)d2i=1dNiσ(i)S(i)d=1Nμ(d)d2i=1dNiσ2(i)d=1Nμ(d)d2i=1dNiσ(i)(2S(i)σ(i)) 如果询问少的话可以 O ( N + T N ) O(N + T\sqrt N) O(N+TN ) 做。


其实所有形如 A ( N ) = ∑ i = 1 N f ( i ) ∑ j = 1 ⌊ N i ⌋ g ( j ) = ∑ i = 1 N ∑ j = 1 ⌊ N i ⌋ f ( i ) g ( j ) A(N)=\sum\limits_{i=1}^{N}f(i)\sum\limits_{j=1}^{\left\lfloor\frac{N}{i}\right\rfloor}g(j)=\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{\left\lfloor\frac{N}{i}\right\rfloor}f(i)g(j) A(N)=i=1Nf(i)j=1iNg(j)=i=1Nj=1iNf(i)g(j) 的式子在已知 f , g f, g f,g 时都可以 O ( N ln ⁡ N ) O(N\ln N) O(NlnN) 预处理所有的 A A A 值。因为它能递推: A ( N ) = A ( N − 1 ) + ( f ∗ g ) ( N ) A(N)=A(N - 1) + (f * g)(N) A(N)=A(N1)+(fg)(N) 考虑 A ( N ) A(N) A(N) A ( N − 1 ) A(N - 1) A(N1) 多出来的东西,无非是当 i ∣ N i|N iN 时, ⌊ N i ⌋ \left\lfloor\frac{N}{i}\right\rfloor iN 多了一个 g ( N i ) g\left(\frac{N}{i}\right) g(iN),因此 A ( N ) = A ( N − 1 ) + ∑ i ∣ N f ( i ) g ( N i ) = A ( N − 1 ) + ( f ∗ g ) ( N ) A(N) = A(N - 1) + \sum_{i|N}f(i)g\left(\frac{N}{i}\right)=A(N - 1) + (f * g)(N) A(N)=A(N1)+iNf(i)g(iN)=A(N1)+(fg)(N) 然后我们用调和级数复杂度算出所有 f ∗ g f*g fg A A A 就是他们的前缀和!


换到这道题上, f ( x ) = μ ( x ) x 2 , g ( x ) = x σ ( x ) ( 2 S ( x ) − σ ( x ) ) f(x)=\mu(x)x^2, g(x)=x\sigma(x)(2S(x)-\sigma(x)) f(x)=μ(x)x2,g(x)=xσ(x)(2S(x)σ(x)),先线筛 μ \mu μ σ \sigma σ,然后预处理即可。

代码

#include <bits/stdc++.h>

int Read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9')
        c = getchar();
    while (c >= '0' && c <= '9')
        x = x * 10 + (c ^ 48), c = getchar();
    return x;
}

typedef long long LL;

const int MAXN = 1000000;
const int MOD = 1000000007;

inline int Add(int x, const int &y) {
    return ((x += y) >= MOD) ? (x - MOD) : x;
}

inline int Mul(const int &x, const int &y) {
    return (LL)x * y % MOD;
}

inline int Sub(int x, const int &y) {
    return ((x -= y) < 0) ? (x + MOD) : x;
}

int Mu[MAXN + 5];
LL Sig[MAXN + 5], Low[MAXN + 5];
bool Vis[MAXN + 5];
std::vector<int> Pri;

int Ans[MAXN + 5], S[MAXN + 5];

void Init(int n) {
    Mu[1] = Sig[1] = Low[1] = S[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!Vis[i])
            Mu[i] = MOD - 1, Sig[i] = Low[i] = 1 + i, Pri.push_back(i);
        for (int j = 0, k; j < (int)Pri.size() && i * Pri[j] <= n; j++) {
            Vis[k = i * Pri[j]] = true;
            if (i % Pri[j] == 0) {
                Mu[k] = 0;
                Low[k] = 1 + Low[i] * Pri[j];
                Sig[k] = Sig[i] / Low[i] * Low[k];
                break;
            }
            Mu[k] = MOD - Mu[i];
            Low[k] = 1 + Pri[j];
            Sig[k] = Sig[i] * Low[k];
        }
        S[i] = Add(S[i - 1], Sig[i] % MOD);
    }
    for (int i = 1; i <= n; i++)
        for (int j = i; j <= n; j += i)
            Ans[j] = Add(Ans[j], Mul(Mu[i], Mul(i, Mul(i, Mul(j / i, Mul(Sig[j / i], Sub(Mul(2, S[j / i]), Sig[j / i])))))));
    for (int i = 1; i <= n; i++)
        Ans[i] = Add(Ans[i], Ans[i - 1]);
}

int main() {
    Init(MAXN);
    int T = Read(), Cas = 0;
    while (T--)
        printf("Case #%d: %d\n", ++Cas, Ans[Read()]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值