题目:BZOJ2154.
题目大意:给定
n
n
n和
m
m
m,求:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)
i=1∑nj=1∑mlcm(i,j)
n , m ≤ 1 0 7 n,m\leq 10^7 n,m≤107.
很容易发现:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
i
=
1
n
∑
j
=
1
m
i
j
g
c
d
(
i
,
j
)
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j) =\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{ij}{gcd(i,j)}
i=1∑nj=1∑mlcm(i,j)=i=1∑nj=1∑mgcd(i,j)ij
我们钦定
n
≤
m
n\leq m
n≤m,那么:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
k
=
1
n
1
k
∑
i
=
1
n
∑
j
=
1
m
i
j
[
g
c
d
(
i
,
j
)
=
k
]
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)\\ =\sum_{k=1}^{n}\frac{1}{k}\sum_{i=1}^{n}\sum_{j=1}^{m}ij[gcd(i,j)=k]
i=1∑nj=1∑mlcm(i,j)=k=1∑nk1i=1∑nj=1∑mij[gcd(i,j)=k]
设
a
=
⌊
n
k
⌋
,
b
=
⌊
m
k
⌋
a=\left \lfloor \frac{n}{k} \right \rfloor,b=\left \lfloor \frac{m}{k} \right \rfloor
a=⌊kn⌋,b=⌊km⌋,那么:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
k
=
1
n
1
k
∑
i
=
1
a
∑
j
=
1
b
i
j
k
2
∗
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
k
=
1
n
k
∑
i
=
1
a
∑
j
=
1
b
i
j
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
=
∑
k
=
1
n
k
∑
d
=
1
a
μ
(
d
)
∑
i
=
1
a
∑
j
=
1
b
i
j
[
d
∣
i
]
[
d
∣
j
]
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)\\ =\sum_{k=1}^{n}\frac{1}{k}\sum_{i=1}^{a}\sum_{j=1}^{b}ijk^2*[gcd(i,j)=1]\\ =\sum_{k=1}^{n}k\sum_{i=1}^{a}\sum_{j=1}^{b}ij\sum_{d|gcd(i,j)}\mu(d)\\ =\sum_{k=1}^{n}k\sum_{d=1}^{a}\mu(d)\sum_{i=1}^{a}\sum_{j=1}^{b}ij[d|i][d|j]
i=1∑nj=1∑mlcm(i,j)=k=1∑nk1i=1∑aj=1∑bijk2∗[gcd(i,j)=1]=k=1∑nki=1∑aj=1∑bijd∣gcd(i,j)∑μ(d)=k=1∑nkd=1∑aμ(d)i=1∑aj=1∑bij[d∣i][d∣j]
设
x
=
⌊
a
d
⌋
,
y
=
⌊
b
d
⌋
x=\left \lfloor \frac{a}{d} \right \rfloor,y=\left \lfloor \frac{b}{d} \right \rfloor
x=⌊da⌋,y=⌊db⌋,那么:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
k
=
1
n
k
∑
d
=
1
a
d
2
μ
(
d
)
∑
i
=
1
x
∑
j
=
1
y
i
j
=
∑
k
=
1
n
k
∑
d
=
1
a
d
2
μ
(
d
)
∗
x
(
x
+
1
)
2
∗
y
(
y
+
1
)
2
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)\\ =\sum_{k=1}^{n}k\sum_{d=1}^{a}d^2\mu(d)\sum_{i=1}^{x}\sum_{j=1}^{y}ij\\ =\sum_{k=1}^{n}k\sum_{d=1}^{a}d^2\mu(d)*\frac{x(x+1)}{2}*\frac{y(y+1)}{2}
i=1∑nj=1∑mlcm(i,j)=k=1∑nkd=1∑ad2μ(d)i=1∑xj=1∑yij=k=1∑nkd=1∑ad2μ(d)∗2x(x+1)∗2y(y+1)
设函数
f
(
x
,
y
)
=
x
(
x
+
1
)
2
∗
y
(
y
+
1
)
2
f(x,y)=\frac{x(x+1)}{2}*\frac{y(y+1)}{2}
f(x,y)=2x(x+1)∗2y(y+1),那么原式就变为:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
k
=
1
n
k
∑
d
=
1
a
d
2
μ
(
d
)
f
(
⌊
a
d
⌋
,
⌊
b
d
⌋
)
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)\\ =\sum_{k=1}^{n}k\sum_{d=1}^{a}d^2\mu(d)f(\left \lfloor \frac{a}{d} \right \rfloor,\left\lfloor \frac{b}{d} \right\rfloor)
i=1∑nj=1∑mlcm(i,j)=k=1∑nkd=1∑ad2μ(d)f(⌊da⌋,⌊db⌋)
设函数(钦定
x
≤
y
x\leq y
x≤y)
g
(
x
,
y
)
=
∑
d
=
1
x
d
2
μ
(
d
)
f
(
⌊
x
d
⌋
,
⌊
y
d
⌋
)
g(x,y)=\sum_{d=1}^{x}d^2\mu(d)f(\left \lfloor \frac{x}{d} \right \rfloor,\left \lfloor \frac{y}{d} \right \rfloor)
g(x,y)=∑d=1xd2μ(d)f(⌊dx⌋,⌊dy⌋),那么原式变为:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
=
∑
k
=
1
n
k
g
(
⌊
n
k
⌋
,
⌊
m
k
⌋
)
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)= \sum_{k=1}^{n}kg(\left\lfloor \frac{n}{k}\right\rfloor,\left\lfloor\frac{m}{k}\right\rfloor)
i=1∑nj=1∑mlcm(i,j)=k=1∑nkg(⌊kn⌋,⌊km⌋)
发现这个式子 g g g函数的计算可以用除法分块优化,而外面式子也可以用除法分块优化,计算这个式子的时间复杂度即为 O ( ( n + m ) 2 ) = O ( n + m ) O((\sqrt{n}+\sqrt{m})^2)=O(n+m) O((n+m)2)=O(n+m).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=10000000;
const LL mod=20101009;
int pr[N+9],tp,b[N+9];
LL mu[N+9],div2;
LL M(LL x){
x=x%mod+mod;
return (x>=mod)?x-=mod:x;
}
void sieve(int n){
for (int i=2;i<=n;++i) b[i]=1;
mu[1]=1;
for (int i=2;i<=n;++i){
if (b[i]) pr[++tp]=i,mu[i]=-1;
for (int j=1;j<=tp&&pr[j]*i<=n;++j){
b[i*pr[j]]=0;
if (i%pr[j]) mu[i*pr[j]]=-mu[i];
else {mu[i*pr[j]]=0;break;}
}
}
for (int i=1;i<=n;++i)
mu[i]=M(mu[i]*i*i+mu[i-1]);
}
LL sum(int l,int r){return M(LL(l+r)*LL(r-l+1)>>1);}
LL f(int x,int y){return M(sum(1,x)*sum(1,y));}
LL g(int n,int m){
LL ans=0;
if (n>m) swap(n,m);
for (int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=M(ans+(mu[r]-mu[l-1])*f(n/l,m/l));
}
return ans;
}
LL Query(int n,int m){
LL ans=0;
if (n>m) swap(n,m);
for (int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=M(ans+sum(l,r)*g(n/l,m/l));
}
return ans;
}
Abigail work(){
sieve(N);
}
Abigail getans(){
int n,m;
scanf("%d%d",&n,&m);
printf("%lld\n",Query(n,m));
}
int main(){
work();
getans();
return 0;
}
我们再来看一道题,是上面这道题多组询问的形式.
题目:BZOJ2693.
题目大意:多组询问,给定
n
n
n和
m
m
m,求:
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)
i=1∑nj=1∑mlcm(i,j)
多组询问了,可是 n n n和 m m m的数据范围还没变,怎么办呢?
我们考虑这样的问题应该是要预处理然后在低于 O ( n ) O(n) O(n)的时间复杂度内回答询问.
观察下式:
∑
k
=
1
n
k
∑
d
=
1
a
μ
(
d
)
d
2
∗
x
(
x
+
1
)
2
∗
y
(
y
+
1
)
x
=
∑
k
=
1
n
k
∑
d
=
1
a
μ
(
d
)
d
2
∗
⌊
n
d
k
⌋
(
⌊
n
d
k
⌋
+
1
)
2
∗
⌊
m
d
k
⌋
(
⌊
m
d
k
⌋
+
1
)
2
\sum_{k=1}^{n}k\sum_{d=1}^{a}\mu(d)d^2*\frac{x(x+1)}{2}*\frac{y(y+1)}{x} \\=\sum_{k=1}^{n}k\sum_{d=1}^{a}\mu(d)d^2*\frac{\left \lfloor \frac{n}{dk} \right \rfloor(\left \lfloor \frac{n}{dk} \right \rfloor+1)}{2} *\frac{\left \lfloor \frac{m}{dk} \right \rfloor(\left \lfloor \frac{m}{dk} \right \rfloor+1)}{2}
k=1∑nkd=1∑aμ(d)d2∗2x(x+1)∗xy(y+1)=k=1∑nkd=1∑aμ(d)d2∗2⌊dkn⌋(⌊dkn⌋+1)∗2⌊dkm⌋(⌊dkm⌋+1)
我们让
t
=
d
k
t=dk
t=dk,那么:
∑
k
=
1
n
k
∑
d
=
1
a
μ
(
d
)
d
2
∗
x
(
x
+
1
)
2
∗
y
(
y
+
1
)
x
=
∑
t
=
1
n
∑
d
∣
t
μ
(
d
)
d
2
∗
t
d
∗
⌊
n
t
⌋
(
⌊
n
t
⌋
+
1
)
2
∗
⌊
m
t
⌋
(
⌊
m
t
⌋
+
1
)
2
=
∑
t
=
1
n
f
(
⌊
n
t
⌋
,
⌊
m
t
⌋
)
∗
t
∑
d
∣
t
μ
(
d
)
∗
d
\sum_{k=1}^{n}k\sum_{d=1}^{a}\mu(d)d^2*\frac{x(x+1)}{2}*\frac{y(y+1)}{x}\\ =\sum_{t=1}^{n}\sum_{d|t}\mu(d)d^2*\frac{t}{d}*\frac{\left \lfloor \frac{n}{t} \right \rfloor(\left \lfloor \frac{n}{t} \right \rfloor+1)}{2} *\frac{\left \lfloor \frac{m}{t} \right \rfloor(\left \lfloor \frac{m}{t} \right \rfloor+1)}{2}\\ =\sum_{t=1}^{n}f(\left \lfloor \frac{n}{t} \right \rfloor,\left \lfloor \frac{m}{t} \right \rfloor)*t\sum_{d|t}\mu(d)*d
k=1∑nkd=1∑aμ(d)d2∗2x(x+1)∗xy(y+1)=t=1∑nd∣t∑μ(d)d2∗dt∗2⌊tn⌋(⌊tn⌋+1)∗2⌊tm⌋(⌊tm⌋+1)=t=1∑nf(⌊tn⌋,⌊tm⌋)∗td∣t∑μ(d)∗d
我们设一个函数
G
(
t
)
=
t
∑
d
∣
t
μ
(
d
)
d
G(t)=t\sum_{d|t}\mu(d)d
G(t)=t∑d∣tμ(d)d,可以证明这个函数是积性的:
当
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1时:
G
(
a
)
G
(
b
)
=
a
∑
d
1
∣
a
μ
(
d
1
)
d
1
∗
b
∑
d
2
∣
b
μ
(
d
2
)
d
2
=
a
b
∑
d
1
∣
a
∑
d
2
∣
b
μ
(
d
1
)
μ
(
d
2
)
d
1
d
2
=
a
b
∑
d
1
∣
a
∑
d
2
∣
b
μ
(
d
1
d
2
)
d
1
d
2
=
a
b
∑
d
∣
a
b
μ
(
d
)
d
=
G
(
a
b
)
G(a)G(b)\\ =a\sum_{d_1|a}\mu(d_1)d_1*b\sum_{d_2|b}\mu(d_2)d_2\\ =ab\sum_{d_1|a}\sum_{d_2|b}\mu(d_1)\mu(d_2)d_1d_2\\ =ab\sum_{d_1|a}\sum_{d_2|b}\mu(d_1d_2)d_1d_2\\ =ab\sum_{d|ab}\mu(d)d\\ =G(ab)
G(a)G(b)=ad1∣a∑μ(d1)d1∗bd2∣b∑μ(d2)d2=abd1∣a∑d2∣b∑μ(d1)μ(d2)d1d2=abd1∣a∑d2∣b∑μ(d1d2)d1d2=abd∣ab∑μ(d)d=G(ab)
证毕.
然后我们就可以用线性筛筛这个函数:
1.当
i
i
i为素数时,
G
(
i
)
=
i
(
μ
(
1
)
+
μ
(
i
)
i
)
=
i
+
i
2
μ
(
i
)
=
i
−
i
2
G(i)=i(\mu(1)+\mu(i)i)=i+i^2\mu(i)=i-i^2
G(i)=i(μ(1)+μ(i)i)=i+i2μ(i)=i−i2.
2.当
g
c
d
(
i
,
p
r
[
j
]
)
=
1
gcd(i,pr[j])=1
gcd(i,pr[j])=1时,根据积性函数的定义,
G
(
i
∗
p
r
[
j
]
)
=
G
(
i
)
G
(
p
r
[
j
]
)
G(i*pr[j])=G(i)G(pr[j])
G(i∗pr[j])=G(i)G(pr[j]).
3.当
p
r
[
j
]
∣
i
pr[j]|i
pr[j]∣i时,可以推导出:
G
(
i
∗
p
r
[
j
]
)
=
i
∗
p
r
[
j
]
∑
d
∣
i
∗
p
r
[
j
]
μ
(
d
)
d
G(i*pr[j])=i*pr[j]\sum_{d|i*pr[j]}\mu(d)d
G(i∗pr[j])=i∗pr[j]d∣i∗pr[j]∑μ(d)d
考虑将式子拆成两部分,一部分为
d
∣
i
d|i
d∣i的情况,另一部分为
g
c
d
(
d
,
i
)
≠
d
gcd(d,i)\neq d
gcd(d,i)̸=d的情况,那么容易发现后者的
μ
\mu
μ值均为
0
0
0,所以:
G
(
i
∗
p
r
[
j
]
)
=
p
r
[
j
]
∗
i
∑
d
∣
i
μ
(
d
)
d
=
p
r
[
j
]
G
(
i
)
G(i*pr[j])=pr[j]*i\sum_{d|i}\mu(d)d=pr[j]G(i)
G(i∗pr[j])=pr[j]∗id∣i∑μ(d)d=pr[j]G(i)
那么我们将
G
G
G函数线性筛出来之后,就可以将原始转变为:
∑
k
=
1
n
k
∑
d
=
1
a
μ
(
d
)
d
2
∗
x
(
x
+
1
)
2
∗
y
(
y
+
1
)
x
=
∑
t
=
1
n
f
(
⌊
n
t
⌋
,
⌊
m
t
⌋
)
G
(
t
)
\sum_{k=1}^{n}k\sum_{d=1}^{a}\mu(d)d^2*\frac{x(x+1)}{2}*\frac{y(y+1)}{x} =\sum_{t=1}^{n}f(\left \lfloor \frac{n}{t} \right \rfloor,\left \lfloor \frac{m}{t} \right \rfloor)G(t)
k=1∑nkd=1∑aμ(d)d2∗2x(x+1)∗xy(y+1)=t=1∑nf(⌊tn⌋,⌊tm⌋)G(t)
发现后面的式子在知道 G G G函数的取值时是可以用除法分块做到 O ( n ) O(\sqrt{n}) O(n)回答一次询问的.
那么我们只需要对 G G G函数进行线性筛并前缀和就可以做到 O ( n + T n ) O(n+T\sqrt{n}) O(n+Tn)解决这个问题了.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const LL mod=100000009; //把模数看成1e9+9死了一次...
const int N=10000000;
LL g[N+9];
int pr[N+9],b[N+9],tp;
LL M(LL x){
x=x%mod+mod;
return x>=mod?x-mod:x;
}
LL f(int x,int y){return M(M(LL(x+1)*x>>1)*M(LL(y+1)*y>>1));}
void sieve(int n){
for (int i=2;i<=n;++i) b[i]=1;
g[1]=1LL;
for (int i=2;i<=n;++i){
if (b[i]) pr[++tp]=i,g[i]=M(LL(1-i)*i);
for (int j=1;j<=tp&&pr[j]*i<=n;++j){
b[i*pr[j]]=0;
if (i%pr[j]) g[i*pr[j]]=M(g[i]*g[pr[j]]);
else {g[i*pr[j]]=M(g[i]*pr[j]);break;}
}
}
for (int i=1;i<=n;++i)
g[i]=M(g[i]+g[i-1]);
}
LL Query(int n,int m){
if (n>m) swap(n,m);
LL ans=0LL;
for (int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=M(ans+f(n/l,m/l)*(g[r]-g[l-1]));
}
return ans;
}
Abigail work(){
sieve(N);
}
Abigail getans(){
int T,n,m;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
printf("%lld\n",Query(n,m));
}
}
int main(){
work();
getans();
return 0;
}