bzoj 4659 题解

题目简述

给定 A A A B B B(多组数据),求

∑ i = 1 n ∑ j = 1 n l c m ( i , j ) μ 2 ( g c d ( i , j ) ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}lcm(i,j)\mu^2(gcd(i,j)) i=1nj=1nlcm(i,j)μ2(gcd(i,j))

已经帮您完成放大操作,不用划鼠标了。。。

数据

输入:
5

2 2

4 6

3 4

5 1

23333 33333
输出:
7

148

48

15

451085813
(还需要解释?自己写暴力。。。)

思路

2333纯数论题我最喜欢了!(数论是我小老婆,大老婆是芙兰朵露·斯卡雷特)
显然这题需要莫比乌斯反演(不会?去看pengym的博客或者我的博客。。。)
根据套路,不妨令A<=B
g c d ( i , j ) = g gcd(i,j)=g gcd(i,j)=g(我懒),原式
= ∑ i = 1 A ∑ j = 1 B i j g μ 2 ( g ) = ∑ d = 1 A ∑ i = 1 A ∑ j = 1 B [ g = d ] μ 2 ( d ) i j d 枚举gcd(i,j),设为d。然后每次找g=d的,这个多想几次就明白了 = ∑ d = 1 A ∑ i = 1 ⌊ A d ⌋ ∑ j = 1 ⌊ B d ⌋ [ g = 1 ] μ 2 ( d ) i j d 这个就是把i,j换成枚举d的倍数,所以右面也换成了ijd,上限也换成了A/d和B/d = ∑ d = 1 A ∑ i = 1 ⌊ A d ⌋ ∑ j = 1 ⌊ B d ⌋ μ 2 ( d ) i j d ∑ q ∣ g μ ( q ) 这个不用解释,就是基本反演式 = ∑ d = 1 A ∑ q = 1 ⌊ A d ⌋ μ ( q ) ∑ i = 1 ⌊ A d ⌋ ∑ j = 1 ⌊ B d ⌋ [ q ∣ g ] μ 2 ( d ) i j d 这个有点思维量,不过也是基本技巧,就是把q提前枚举了,后面找q|g的 = ∑ d = 1 A ∑ q = 1 ⌊ A d ⌋ μ ( q ) ∑ i = 1 ⌊ A d q ⌋ ∑ j = 1 ⌊ B d q ⌋ [ 1 ∣ g ] μ 2 ( d ) i j d q 2 这个就是把i,j换成了枚举dq的倍数,所以后面多乘一个 q 2 。而且1|g是废话,珂以删掉 = ∑ d = 1 A d μ 2 ( d ) ∑ q = 1 ⌊ A d ⌋ μ ( q ) q 2 ( ∑ i = 1 ⌊ A d q ⌋ i ) ( ∑ j = 1 ⌊ B d q ⌋ j ) 这一步就是把一些无关的东西提到了最前面 其中 ( ∑ i = 1 ⌊ A d q ⌋ i ) 和 ( ∑ j = 1 ⌊ B d q ⌋ j ) 珂以用高斯求和公式(就是1加到100那个广为人知的故事) O ( 1 ) 求出来 设 S ( n ) = n ( n + 1 ) 2 ,原式 = ∑ d = 1 A d μ 2 ( d ) ∑ q = 1 ⌊ A d ⌋ μ ( q ) q 2 S ( ⌊ A d q ⌋ ) S ( ⌊ B d q ⌋ ) 设 D = d q ,原式 = ∑ D = 1 ∑ d ∣ D d μ 2 ( d ) μ ( D d ) ( D d ) 2 S ( ⌊ A D ⌋ ) S ( ⌊ B D ⌋ ) 这边就是把d和q一起枚举了,所以 ∑ 的条件就变成了 d ∣ D 设 f ( x ) = x μ 2 ( x ) , g ( x ) = μ ( x ) x 2 ,(细心的同学会发现我就是在凑卷积)原式 = ∑ D = 1 ∑ d ∣ D f ( d ) g ( D d ) S ( ⌊ A D ⌋ ) S ( ⌊ B D ⌋ ) 简单的代入,不过这时候已经很像狄利克雷卷积了 = ∑ D = 1 S ( ⌊ A D ⌋ ) S ( ⌊ B D ⌋ ) ∑ d ∣ D f ( d ) g ( D d ) 把无关的提到前面 设 h = f ∗ g ,原式 = ∑ D = 1 S ( ⌊ A D ⌋ ) S ( ⌊ B D ⌋ ) h ( D ) =\sum\limits_{i=1}^{A}\sum\limits_{j=1}^{B}\frac{ij}{g}\mu^2(g)\\ =\sum\limits_{d=1}^{A} \sum\limits_{i=1}^{A}\sum\limits_{j=1}^{B}[g=d]\mu^2(d)\frac{ij}{d}\\ \text{枚举gcd(i,j),设为d。然后每次找g=d的,这个多想几次就明白了}\\ =\sum\limits_{d=1}^{A} \sum\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{B}{d}\rfloor}[g=1]\mu^2(d)ijd\\ \text{这个就是把i,j换成枚举d的倍数,所以右面也换成了ijd,上限也换成了A/d和B/d}\\ =\sum\limits_{d=1}^{A} \sum\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{B}{d}\rfloor}\mu^2(d)ijd\sum\limits_{q|g}\mu(q)\\ \text{这个不用解释,就是基本反演式}\\ =\sum\limits_{d=1}^{A}\sum\limits_{q=1}^{\lfloor\frac{A}{d}\rfloor}\mu(q)\sum\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{B}{d}\rfloor}[q|g]\mu^2(d)ijd\\ \text{这个有点思维量,不过也是基本技巧,就是把q提前枚举了,后面找q|g的}\\ =\sum\limits_{d=1}^{A}\sum\limits_{q=1}^{\lfloor\frac{A}{d}\rfloor}\mu(q)\sum\limits_{i=1}^{\lfloor\frac{A}{dq}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{B}{dq}\rfloor}[1|g]\mu^2(d)ijdq^2\\ \text{这个就是把i,j换成了枚举dq的倍数,所以后面多乘一个} q^2\text{。而且1|g是废话,珂以删掉}\\ =\sum\limits_{d=1}^{A}d\mu^2(d)\sum\limits_{q=1}^{\lfloor\frac{A}{d}\rfloor}\mu(q)q^2(\sum\limits_{i=1}^{\lfloor\frac{A}{dq}\rfloor}i)(\sum\limits_{j=1}^{\lfloor\frac{B}{dq}\rfloor}j)\\ \text{这一步就是把一些无关的东西提到了最前面}\\ \text{其中}\\ (\sum\limits_{i=1}^{\lfloor\frac{A}{dq}\rfloor}i)和(\sum\limits_{j=1}^{\lfloor\frac{B}{dq}\rfloor}j)\\ \text{珂以用高斯求和公式(就是1加到100那个广为人知的故事)}O(1)\text{求出来}\\ \text{设}S(n)=\frac{n(n+1)}{2}\text{,原式}\\ =\sum\limits_{d=1}^{A}d\mu^2(d)\sum\limits_{q=1}^{\lfloor\frac{A}{d}\rfloor}\mu(q)q^2S(\lfloor\frac{A}{dq}\rfloor)S(\lfloor\frac{B}{dq}\rfloor)\\ \text{设}D=dq\text{,原式}\\ =\sum\limits_{D=1}\sum\limits_{d|D}d\mu^2(d)\mu(\frac{D}{d})({\frac{D}{d}})^2S(\lfloor\frac{A}{D}\rfloor)S(\lfloor\frac{B}{D}\rfloor)\\ \text{这边就是把d和q一起枚举了,所以}\sum \text{的条件就变成了}d|D\\ \text{设}f(x)=x\mu^2(x),g(x)=\mu(x)x^2 \text{,(细心的同学会发现我就是在凑卷积)原式}\\ =\sum\limits_{D=1}\sum\limits_{d|D}f(d)g(\frac{D}{d})S(\lfloor\frac{A}{D}\rfloor)S(\lfloor\frac{B}{D}\rfloor)\\ \text{简单的代入,不过这时候已经很像狄利克雷卷积了}\\ =\sum\limits_{D=1}S(\lfloor\frac{A}{D}\rfloor)S(\lfloor\frac{B}{D}\rfloor)\sum\limits_{d|D}f(d)g(\frac{D}{d})\\ \text{把无关的提到前面}\\ \text{设}h=f*g\text{,原式} =\sum\limits_{D=1}S(\lfloor\frac{A}{D}\rfloor)S(\lfloor\frac{B}{D}\rfloor)h(D)\\ =i=1Aj=1Bgijμ2(g)=d=1Ai=1Aj=1B[g=d]μ2(d)dij枚举gcd(i,j),设为d。然后每次找g=d的,这个多想几次就明白了=d=1Ai=1dAj=1dB[g=1]μ2(d)ijd这个就是把i,j换成枚举d的倍数,所以右面也换成了ijd,上限也换成了A/dB/d=d=1Ai=1dAj=1dBμ2(d)ijdqgμ(q)这个不用解释,就是基本反演式=d=1Aq=1dAμ(q)i=1dAj=1dB[qg]μ2(d)ijd这个有点思维量,不过也是基本技巧,就是把q提前枚举了,后面找q|g=d=1Aq=1dAμ(q)i=1dqAj=1dqB[1g]μ2(d)ijdq2这个就是把i,j换成了枚举dq的倍数,所以后面多乘一个q2。而且1|g是废话,珂以删掉=d=1Adμ2(d)q=1dAμ(q)q2(i=1dqAi)(j=1dqBj)这一步就是把一些无关的东西提到了最前面其中(i=1dqAi)(j=1dqBj)珂以用高斯求和公式(就是1加到100那个广为人知的故事)O(1)求出来S(n)=2n(n+1),原式=d=1Adμ2(d)q=1dAμ(q)q2S(dqA)S(dqB)D=dq,原式=D=1dDdμ2(d)μ(dD)(dD)2S(DA)S(DB)这边就是把dq一起枚举了,所以的条件就变成了dDf(x)=xμ2(x),g(x)=μ(x)x2(细心的同学会发现我就是在凑卷积)原式=D=1dDf(d)g(dD)S(DA)S(DB)简单的代入,不过这时候已经很像狄利克雷卷积了=D=1S(DA)S(DB)dDf(d)g(dD)把无关的提到前面h=fg,原式=D=1S(DA)S(DB)h(D)
显然到这里珂以打整除分块了。 h h h珂以和筛 μ \mu μ类似的方法线性筛出来。显然, h ( p ) ( p 为 质 数 ) = 1 − p h(p)(p为质数)=1-p h(p)(p)=1p,然后在推一下别的东西,代码就出来了。此处略讲,自己想想。

西江月·证明
既得易见平凡,仿照上例显然。留作习题答案略,读者自证不难。
反之亦然同理,推论自然成立。略去过程QED,由上可知证毕。

有一点注意,由于模的是 2 30 2^{30} 230,所以珂以让其自然溢出,然后&一下 ( 1 &lt; &lt; 30 ) − 1 (1&lt;&lt;30)-1 (1<<30)1即可。
代码:

#include<bits/stdc++.h>
#define N 4001000
#define int long long
#define mod 0x3fffffff
using namespace std;

int primes[N];bool notp[N];
int h[N];

void Init()//筛h函数
{
    int& cnt=primes[0];
    int n=4000000;
    h[1]=notp[1]=1;

    for(int i=2;i<=n;i++)
    {
        if (!notp[i])
        {
            primes[++cnt]=i;
            h[i]=1-i;
        }
        for(int j=1;j<=cnt and i*primes[j]<=n;j++)
        {
            int u=primes[j];
            notp[i*u]=1;
            if (i%u!=0)
            {
                h[i*u]=h[i]*(1-u);
            }
            else
            {
                if (i%(u*u)==0) h[i*u]=0;
                else h[i*u]=-h[i/u]*u;
                break;
            }
        }
    }

    for(int i=1;i<=n;i++)
    {
        h[i]=h[i]*i+h[i-1];
    }
}

int A,B;

int sum(int x)//高斯求和公式
{
    return x*(x+1)/2;
}
void Solve()
{
    int ans=0;
    for(int l=1,r;l<=A;l=r+1)
    {
        r=min(A/(A/l),B/(B/l));//两个整除分块
        ans+=(h[r]-h[l-1])*sum(A/l)*sum(B/l);//这个很简单吧。。。
    }
    printf("%d\n",ans&mod);
}
void Query()
{
    int T;scanf("%lld",&T);
    while(T-->0)
    {
        scanf("%lld%lld",&A,&B);
        if (A>B) A^=B^=A^=B;
        //A要<=B
        Solve();
    }
}

main()
{
    Init();
    Query();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值