如果不知道莫比乌斯 这里有我的超精简版入门Mobius
记录我初学莫比乌斯做了整整一天还迷迷糊糊
题目简述:
求
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
d
(
i
j
)
为
i
∗
j
的
约
数
∑_{i=1}^n∑_{j=1}^md(ij)\\d(ij)为i*j的约数
i=1∑nj=1∑md(ij)d(ij)为i∗j的约数(多组数据)
必要性质:
d
(
i
j
)
=
∑
x
∣
i
∑
y
∣
j
g
c
d
(
x
,
y
)
=
1
d(ij)=∑_{x|i}∑_{y|j}gcd(x,y)=1
d(ij)=x∣i∑y∣j∑gcd(x,y)=1
证明:
不会
解题思路:
所
求
即
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
g
c
d
(
x
,
y
)
=
1
所求即∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}gcd(x,y)=1
所求即i=1∑nj=1∑mx∣i∑y∣j∑gcd(x,y)=1
根
据
莫
比
乌
斯
函
数
的
性
质
可
转
换
为
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
∣
g
c
d
(
x
,
y
)
μ
(
d
)
根据莫比乌斯函数的性质可转换为\\ ∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}∑_{d|gcd(x,y)}μ(d)\\
根据莫比乌斯函数的性质可转换为i=1∑nj=1∑mx∣i∑y∣j∑d∣gcd(x,y)∑μ(d)
转
换
为
转换为\\
转换为
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∗
[
d
∣
g
c
d
(
x
,
y
)
]
∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}∑_{d=1}^{min(n,m)}μ(d)*[d|gcd(x,y)]
i=1∑nj=1∑mx∣i∑y∣j∑d=1∑min(n,m)μ(d)∗[d∣gcd(x,y)]
即
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
d
∣
g
c
d
(
x
,
y
)
]
即\\ ∑_{d=1}^{min(n,m)}μ(d)∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}[d|gcd(x,y)]\\
即d=1∑min(n,m)μ(d)i=1∑nj=1∑mx∣i∑y∣j∑[d∣gcd(x,y)]
每
个
d
如
果
在
当
前
x
,
y
处
合
法
,
那
么
在
x
,
y
的
倍
数
处
也
一
定
合
法
,
即
每个d如果在当前x,y处合法,那么在x,y的倍数处也一定合法,即\\
每个d如果在当前x,y处合法,那么在x,y的倍数处也一定合法,即
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
x
=
1
n
∑
y
=
1
m
[
d
∣
g
c
d
(
x
,
y
)
]
⌊
n
x
⌋
⌊
m
y
⌋
∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^n∑_{y=1}^m[d|gcd(x,y)]\lfloor\frac{n}{x}\rfloor\lfloor \frac{m}{y}\rfloor\\
d=1∑min(n,m)μ(d)x=1∑ny=1∑m[d∣gcd(x,y)]⌊xn⌋⌊ym⌋
[
d
∣
g
c
d
(
x
,
y
)
]
的
意
义
即
为
x
,
y
的
公
因
数
[d|gcd(x,y)]的意义即为x,y的公因数
[d∣gcd(x,y)]的意义即为x,y的公因数
下
面
进
行
枚
举
项
转
换
,
直
接
枚
举
倍
数
\\下面进行枚举项转换,直接枚举倍数\\
下面进行枚举项转换,直接枚举倍数
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
x
=
1
n
/
d
∑
y
=
1
m
/
d
⌊
n
d
x
⌋
⌊
m
d
y
⌋
即
∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^{n/d}∑_{y=1}^{m/d}\lfloor\frac{n}{dx}\rfloor\lfloor \frac{m}{dy}\rfloor \\即
d=1∑min(n,m)μ(d)x=1∑n/dy=1∑m/d⌊dxn⌋⌊dym⌋即
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
(
∑
x
=
1
n
/
d
⌊
n
d
x
⌋
)
(
∑
y
=
1
m
/
d
⌊
m
d
y
⌋
)
∑_{d=1}^{min(n,m)}μ(d)(∑_{x=1}^{n/d}\lfloor\frac{n}{dx}\rfloor)(∑_{y=1}^{m/d}\lfloor \frac{m}{dy}\rfloor)\\
d=1∑min(n,m)μ(d)(x=1∑n/d⌊dxn⌋)(y=1∑m/d⌊dym⌋)
对
于
多
组
数
据
我
们
即
可
预
处
理
∑
x
=
1
n
n
x
提
高
速
率
对于多组数据我们即可预处理∑_{x=1}^{n}\frac{n}{x}提高速率
对于多组数据我们即可预处理x=1∑nxn提高速率
#include<iostream>
#include<algorithm>
using namespace std;
#define N 50010
int T;
int mu[N],prim[N],cnt,k,g[N];
long long sum[N];
bool vis[N];
inline void get(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){//i为质数
mu[i]=-1;prim[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prim[j]<=n;j++)
{
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;//i*prim[j]指数的大于1
else mu[i*prim[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(long long)mu[i];
for(int i=1;i<=n;i++){
long long ans=0;
for(int l=1,r;l<=i;l=r+1){
r=(i/(i/l));
ans+=(r-l+1)*1ll*(i/l);
}
g[i]=ans;
}
}
inline long long calc(int a,int b){
int maxx;
long long ans=0;
maxx=min(a,b);
for(int l=1,r;l<=maxx;l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=1ll*g[a/l]*g[b/l]*(sum[r]-sum[l-1]);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>T;
get(N);
while(T--){
int a,b;
cin>>a>>b;
cout<<calc(a,b)<<endl;
}
return 0;
}