题目链接:
洛谷
莫比乌斯反演+整除分块
q
w
q
qwq
qwq
如果不会莫比乌斯反演,珂以看我的博客qwq
做这道题之前珂以先看HDU1695和我的题解qwq
先把答案表示出来:
a
n
s
=
Σ
i
=
1
N
Σ
j
=
1
M
[
g
c
d
(
i
,
j
)
为
质
数
]
ans=\Large\Sigma\large_{i=1}^N\Large\Sigma\large_{j=1}^M[gcd(i,j)为质数]
ans=Σi=1NΣj=1M[gcd(i,j)为质数]
发现“为质数”不太好转化,珂以考虑把
g
c
d
(
i
,
j
)
gcd(i,j)
gcd(i,j)提前枚举:
=
Σ
p
为
质
数
Σ
i
=
1
N
Σ
j
=
1
M
[
g
c
d
(
i
,
j
)
=
=
p
]
=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{i=1}^N\Large\Sigma\large_{j=1}^M[gcd(i,j)==p]
=Σp为质数Σi=1NΣj=1M[gcd(i,j)==p]
同
h
d
u
1695
hdu1695
hdu1695的推法,这里珂以把
i
,
j
i,j
i,j同时除以
p
p
p:
=
Σ
p
为
质
数
Σ
i
=
1
N
/
p
Σ
j
=
1
M
/
p
[
g
c
d
(
i
,
j
)
=
=
1
]
=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{i=1}^{N/p}\Large\Sigma\large_{j=1}^{M/p}[gcd(i,j)==1]
=Σp为质数Σi=1N/pΣj=1M/p[gcd(i,j)==1]
令
f
(
n
)
f(n)
f(n)表示
g
c
d
(
i
,
j
)
=
=
n
gcd(i,j)==n
gcd(i,j)==n的个数,
F
(
n
)
F(n)
F(n)表示
n
∣
g
c
d
(
i
,
j
)
n|gcd(i,j)
n∣gcd(i,j)的个数。
则
F
(
n
)
=
Σ
n
∣
d
f
(
d
)
F(n)=\Large\Sigma\large_{n|d}f(d)
F(n)=Σn∣df(d)
做一下莫比乌斯反演得
f
(
n
)
=
Σ
n
∣
d
μ
(
d
n
)
F
(
d
)
=
Σ
n
∣
d
μ
(
d
n
)
⌊
N
d
⌋
⌊
M
d
⌋
f(n)=\Large\Sigma\large_{n|d}\mu(\frac{d}{n})F(d)=\Large\Sigma\large_{n|d}\mu(\frac{d}{n})\lfloor\frac{N}{d}\rfloor\lfloor\frac{M}{d}\rfloor
f(n)=Σn∣dμ(nd)F(d)=Σn∣dμ(nd)⌊dN⌋⌊dM⌋
所以
a
n
s
=
Σ
p
为
质
数
Σ
p
∣
d
μ
(
d
p
)
F
(
d
)
ans=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{p|d}\mu(\frac{d}{p})F(d)
ans=Σp为质数Σp∣dμ(pd)F(d)
令
d
p
=
t
\frac{d}{p}=t
pd=t,把式子改为枚举
t
t
t:
a
n
s
=
Σ
p
为
质
数
Σ
t
=
1
m
i
n
(
n
,
m
)
/
p
μ
(
t
)
F
(
t
p
)
=
Σ
p
为
质
数
Σ
t
=
1
m
i
n
(
n
,
m
)
/
p
μ
(
t
)
⌊
N
t
p
⌋
⌊
M
t
p
⌋
ans=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{t=1}^{min(n,m)/p}\mu(t)F(tp)=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{t=1}^{min(n,m)/p}\mu(t)\lfloor\frac{N}{tp}\rfloor\lfloor\frac{M}{tp}\rfloor
ans=Σp为质数Σt=1min(n,m)/pμ(t)F(tp)=Σp为质数Σt=1min(n,m)/pμ(t)⌊tpN⌋⌊tpM⌋
令
T
=
t
p
T=tp
T=tp,则
a
n
s
=
Σ
Σ
μ
(
T
t
)
⌊
N
T
⌋
⌊
M
T
⌋
ans=\Large\Sigma\large\Large\Sigma\large\mu(\frac{T}{t})\lfloor\frac{N}{T}\rfloor\lfloor\frac{M}{T}\rfloor
ans=ΣΣμ(tT)⌊TN⌋⌊TM⌋
=
Σ
T
=
1
m
i
n
(
n
,
m
)
⌊
N
T
⌋
⌊
M
T
⌋
Σ
t
∣
T
μ
(
T
t
)
=\Large\Sigma\large_{T=1}^{min(n,m)}\lfloor\frac{N}{T}\rfloor\lfloor\frac{M}{T}\rfloor\Large\Sigma\large_{t|T}\mu(\frac{T}{t})
=ΣT=1min(n,m)⌊TN⌋⌊TM⌋Σt∣Tμ(tT)
然后整除分块+前缀和就珂以了qwq
上代码:
#include<stdio.h>
#include<algorithm>
#define re register int
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
const int Size=10000005;
ll n,m,sum[Size],f[Size];
int tot,p[Size],prime[Size/10];
bool vis[Size];
void getp(int maxn) {
p[1]=1;
for(re i=2; i<=maxn; i++) {
if(!vis[i]) {
p[i]=-1;
prime[++tot]=i;
}
for(re j=1; j<=tot && i*prime[j]<=maxn; j++) {
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
p[i*prime[j]]=-p[i];
}
}
for(re i=1; i<=tot; i++) {
for(re j=1; j*prime[i]<=maxn; j++) {
f[j*prime[i]]+=p[j];
}
}
for(re i=1; i<=maxn; i++) {
// sum[i]+=sum[i-1];
sum[i]=sum[i-1]+f[i];
}
}
int main() {
getp(10000000);
int T=read();
while(T--) {
n=read();
m=read();
int maxn=min(n,m),lst;
ll ans=0;
for(re i=1; i<=maxn; i=lst+1) {
lst=min(n/(n/i),m/(m/i));
ans+=(ll)(n/i)*(m/i)*(sum[lst]-sum[i-1]);
}
printf("%lld\n",ans);
}
return 0;
}