题目大意: 求 ∑ i = 1 n ∑ j = 1 m d ( i j ) \sum_{i=1}^n \sum_{j=1}^m d(ij) ∑i=1n∑j=1md(ij), d ( x ) d(x) d(x) 是 x x x 的因数个数。
题解
首先要知道
d
d
d 的一个性质,有了这个性质就可以愉快地推柿子了!
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
=
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
gcd
(
x
,
y
)
=
1
]
\sum_{i=1}^n \sum_{j=1}^m d(ij)\\ =\sum_{i=1}^n \sum_{j=1}^m \sum_{x|i} \sum_{y|j} [\gcd(x,y)=1]
i=1∑nj=1∑md(ij)=i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]
更改枚举对象,于是有
=
∑
x
=
1
n
∑
y
=
1
m
[
gcd
(
x
,
y
)
=
1
]
⌊
n
x
⌋
⌊
m
y
⌋
=\sum_{x=1}^n \sum_{y=1}^m [\gcd(x,y)=1]\lfloor \frac n x \rfloor \lfloor \frac m y \rfloor
=x=1∑ny=1∑m[gcd(x,y)=1]⌊xn⌋⌊ym⌋
套个莫比乌斯反演(强行安利博客qwq),于是变成
=
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
∑
d
∣
g
c
d
(
x
,
y
)
μ
(
d
)
=
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
∑
d
=
1
min
(
n
,
m
)
μ
(
d
)
[
d
∣
gcd
(
x
,
y
)
]
=
∑
d
=
1
min
(
n
,
m
)
μ
(
d
)
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
[
d
∣
gcd
(
x
,
y
)
]
=
∑
d
=
1
min
(
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
⌋
⌊
n
d
x
⌋
∑
y
=
1
⌊
m
d
⌋
⌊
m
d
y
⌋
=\sum_{x=1}^n \sum_{y=1}^m \lfloor \frac n x \rfloor \lfloor \frac m y \rfloor \sum_{d|gcd(x,y)} \mu(d)\\ =\sum_{x=1}^n \sum_{y=1}^m \lfloor \frac n x \rfloor \lfloor \frac m y \rfloor \sum_{d=1}^{\min(n,m)}\mu(d)[d|\gcd(x,y)]\\ =\sum_{d=1}^{\min(n,m)}\mu(d)\sum_{x=1}^n \sum_{y=1}^m \lfloor \frac n x \rfloor \lfloor \frac m y \rfloor [d|\gcd(x,y)]\\ =\sum_{d=1}^{\min(n,m)}\mu(d) \sum_{x=1}^{\lfloor \frac n d \rfloor} \sum_{y=1}^{\lfloor \frac m d \rfloor} \lfloor \frac n {dx} \rfloor \lfloor \frac m {dy} \rfloor\\ =\sum_{d=1}^{\min(n,m)}\mu(d) \sum_{x=1}^{\lfloor \frac n d \rfloor} \lfloor \frac n {dx} \rfloor \sum_{y=1}^{\lfloor \frac m d \rfloor} \lfloor \frac m {dy} \rfloor
=x=1∑ny=1∑m⌊xn⌋⌊ym⌋d∣gcd(x,y)∑μ(d)=x=1∑ny=1∑m⌊xn⌋⌊ym⌋d=1∑min(n,m)μ(d)[d∣gcd(x,y)]=d=1∑min(n,m)μ(d)x=1∑ny=1∑m⌊xn⌋⌊ym⌋[d∣gcd(x,y)]=d=1∑min(n,m)μ(d)x=1∑⌊dn⌋y=1∑⌊dm⌋⌊dxn⌋⌊dym⌋=d=1∑min(n,m)μ(d)x=1∑⌊dn⌋⌊dxn⌋y=1∑⌊dm⌋⌊dym⌋
设
g
(
x
)
=
∑
i
=
1
x
⌊
x
i
⌋
g(x)=\sum_{i=1}^x \lfloor \frac x i \rfloor
g(x)=∑i=1x⌊ix⌋,那么柿子变成
=
∑
d
=
1
min
(
n
,
m
)
μ
(
d
)
×
g
(
⌊
n
d
⌋
)
×
g
(
⌊
m
d
⌋
)
=\sum_{d=1}^{\min(n,m)}\mu(d) \times g(\lfloor \frac n d \rfloor) \times g(\lfloor \frac m d \rfloor)
=d=1∑min(n,m)μ(d)×g(⌊dn⌋)×g(⌊dm⌋)
先用除法分块预处理 g g g,然后线性筛出 μ \mu μ ,在求个前缀和,最后上面这条式子用除法分块搞一搞即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 50010
#define ll long long
int t,n,m;
ll ans;
ll mu[maxn],g[maxn];
int prime[maxn],tt=0;
bool v[maxn];
void work()
{
mu[1]=1;
for(int i=2;i<=maxn-10;i++)//线性筛mu
{
if(!v[i])prime[++tt]=i,mu[i]=-1;
for(int j=1;j<=tt&&i*prime[j]<=maxn-10;j++)
{
v[i*prime[j]]=true;
if(i%prime[j]==0)break;
mu[i*prime[j]]=mu[i]*mu[prime[j]];
}
}
for(int i=2;i<=maxn-10;i++)//求前缀和
mu[i]+=mu[i-1];
int l,r;
for(int i=1;i<=maxn-10;i++)//求g
{
l=1;
while(l<=i)
{
r=i/(i/l);
g[i]+=(ll)(r-l+1)*(i/l);
l=r+1;
}
}
}
int main()
{
scanf("%d",&t);
work();
while(t--)
{
scanf("%d %d",&n,&m);
ans=0;
int l=1,r;
while(l<=min(n,m))//除法分块求解
{
r=min(n/(n/l),m/(m/l));
ans+=(mu[r]-mu[l-1])*g[n/l]*g[m/l];
l=r+1;
}
printf("%lld\n",ans);
}
}