题目传送门
前置: 对于函数 f ( x ) f(x) f(x)和 F ( x ) F(x) F(x)。
如果有
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n)=\sum\limits_{d|n}f( d )
F(n)=d∣n∑f(d),那么有
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
F
(
n
d
)
f(n)=\sum\limits_{d|n} \mu(d)F(\cfrac nd)
f(n)=d∣n∑μ(d)F(dn)
如果有
F
(
n
)
=
∑
n
∣
d
f
(
d
)
F(n)=\sum\limits_{n|d}f(d)
F(n)=n∣d∑f(d),那么有
f
(
n
)
=
∑
n
∣
d
μ
(
d
n
)
F
(
d
)
f(n)=\sum\limits_{n|d} \mu(\cfrac dn)F(d)
f(n)=n∣d∑μ(nd)F(d)
题意: T T T组询问,给你 a , b , d a,b,d a,b,d,求出 1 ≤ x ≤ a , 1 ≤ y ≤ b , g c d ( x , y ) = d 1\le x \le a,1 \le y \le b,gcd(x,y)=d 1≤x≤a,1≤y≤b,gcd(x,y)=d 的数量。
思路: 以下推导中,除法均为整数。
f
(
d
)
=
∑
x
=
1
a
∑
y
=
1
b
[
g
c
d
(
x
,
y
)
=
d
]
f(d) = \sum\limits_{x=1}^a \sum\limits_{y=1}^b [gcd(x,y)=d]
f(d)=x=1∑ay=1∑b[gcd(x,y)=d]
F
(
n
)
=
∑
n
∣
k
f
(
k
)
=
∑
n
∣
k
∑
x
=
1
a
∑
y
=
1
b
[
g
c
d
(
x
,
y
)
=
k
]
=
∑
x
=
1
a
∑
y
=
1
b
[
n
∣
g
c
d
(
x
,
y
)
]
=
∑
x
=
1
a
[
n
∣
x
]
∑
y
=
1
b
[
n
∣
y
]
=
a
n
∗
b
n
\begin{aligned} F(n) &=\sum\limits_{n|k}f(k)\\ &=\sum\limits_{n|k}\sum\limits_{x=1}^a \sum\limits_{y=1}^b [gcd(x,y)=k]\\ &=\sum\limits_{x=1}^a \sum\limits_{y=1}^b [n|gcd(x,y)]\\ &=\sum\limits_{x=1}^a[n|x]\sum\limits_{y=1}^b[n|y]\\ &=\cfrac{a}{n}*\cfrac{b}{n}\\ \end{aligned}
F(n)=n∣k∑f(k)=n∣k∑x=1∑ay=1∑b[gcd(x,y)=k]=x=1∑ay=1∑b[n∣gcd(x,y)]=x=1∑a[n∣x]y=1∑b[n∣y]=na∗nb
由于有第一步的 F ( n ) = ∑ n ∣ k f ( k ) F(n) =\sum\limits_{n|k}f(k) F(n)=n∣k∑f(k) ,所以有 f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) f(d)=\sum\limits_{d|k}\mu(\cfrac{k}{d})F(k) f(d)=d∣k∑μ(dk)F(k)。
f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) = ∑ d ∣ k μ ( k d ) ∗ a k ∗ b k \begin{aligned} f(d)&=\sum\limits_{d|k}\mu(\cfrac{k}{d})F(k)\\ &=\sum\limits_{d|k}\mu(\cfrac{k}{d})*\cfrac{a}{k}*\cfrac{b}{k}\end{aligned} f(d)=d∣k∑μ(dk)F(k)=d∣k∑μ(dk)∗ka∗kb
设 t = k d t=\cfrac kd t=dk,
f ( d ) = ∑ t = 1 μ ( t ) a t ∗ d ∗ b t ∗ d = ∑ t = 1 μ ( t ) a d t ∗ b d t \begin{aligned} f(d)&=\sum\limits_{t=1}\mu(t)\cfrac{a}{t*d}*\cfrac{b}{t*d}\\ &=\sum\limits_{t=1}\mu(t)\cfrac{\cfrac ad}{t}*\cfrac{\cfrac bd}{t} \end{aligned} f(d)=t=1∑μ(t)t∗da∗t∗db=t=1∑μ(t)tda∗tdb
莫比乌斯函数用欧拉筛筛出来,做一下前缀和,接下来就可以用除法分块计算答案了,时间复杂度为 O ( T n ) O(T\sqrt n) O(Tn)。
代码:
bool ok[N];
int p[N],mu[N];
void euler()
{
mu[1] = 1;
for(int i=2; i<N; i++)
{
if(!ok[i])
{
p[++p[0]] = i;
mu[i] = -1;
}
for(int j=1; j<=p[0]&&p[j]*i<N; j++)
{
ok[p[j]*i] = 1;
if(i%p[j]==0)
mu[i*p[j]] = 0;
else mu[i*p[j]] = -mu[i];
}
}
for(int i=2; i<N; i++)
mu[i] += mu[i-1];
}
signed main()
{
int t;
cin>>t;
euler();
while(t--)
{
int a,b,d;
cin>>a>>b>>d;
a/=d;
b/=d;
int mi = min(a,b);
int res = 0;
for(int i=1,j; i<=mi; i=j+1)
{
j = min(a/(a/i),b/(b/i));
res += (a/i) * (b/i) * (mu[j]-mu[i-1]);
}
cout<<res<<endl;
}
return 0;
}