题目传送门
题意: n n n组询问,每次询问 a , b , c , d , k a,b,c,d,k a,b,c,d,k,求 a n s = ∑ i = a b ∑ j = c d [ g c d ( i , j ) = k ] ans=\sum\limits_{i=a}^{b}\sum\limits_{j=c}^{d}[gcd(i,j)=k] ans=i=a∑bj=c∑d[gcd(i,j)=k]。
思路:设
f
(
n
,
m
)
=
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
k
]
f(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)=k]
f(n,m)=i=1∑nj=1∑m[gcd(i,j)=k],我们对上面这个式子处理一下,得到
a
n
s
=
f
(
b
,
d
)
−
f
(
b
,
c
−
1
)
−
f
(
a
−
1
,
d
)
+
f
(
a
−
1
,
c
−
1
)
ans=f(b,d)-f(b,c-1)-f(a-1,d)+f(a-1,c-1)
ans=f(b,d)−f(b,c−1)−f(a−1,d)+f(a−1,c−1)
f
(
n
,
m
)
=
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
k
]
=
∑
i
=
1
⌊
n
k
⌋
∑
j
=
1
⌊
m
k
⌋
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
i
=
1
⌊
n
k
⌋
∑
j
=
1
⌊
m
k
⌋
∑
d
∣
(
i
,
j
)
μ
(
d
)
=
∑
d
=
1
n
μ
(
d
)
⌊
⌊
n
k
⌋
d
⌋
∗
⌊
⌊
m
k
⌋
d
⌋
\begin{aligned}\\ f(n,m)&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)=k]\\ &=\sum\limits_{i=1}^{\lfloor \frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{k}\rfloor}[gcd(i,j)=1]\\ &=\sum\limits_{i=1}^{\lfloor \frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{k}\rfloor}\sum\limits_{d|(i,j)}\mu(d)\\ &=\sum\limits_{d=1}^{n}\mu(d) \lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor * \lfloor\frac{\lfloor\frac{m}{k}\rfloor}{d}\rfloor \end{aligned}
f(n,m)=i=1∑nj=1∑m[gcd(i,j)=k]=i=1∑⌊kn⌋j=1∑⌊km⌋[gcd(i,j)=1]=i=1∑⌊kn⌋j=1∑⌊km⌋d∣(i,j)∑μ(d)=d=1∑nμ(d)⌊d⌊kn⌋⌋∗⌊d⌊km⌋⌋
然后我们就可以通过数论分块求答案了。
C o d e Code Code
// Author : ACfunhsl
// Time : 2021/5/17 14:13:11
const int N = 1e5+50;
bool ok[N];
int p[N],cnt=0,mu[N];
void euler()
{
mu[1] = 1;
for(int i=2;i<N;i++)
{
if(!ok[i])
{
p[++cnt] = i;
mu[i] = -1;
}
for(int j=1;j<=cnt&&i*p[j]<N;j++)
{
ok[i*p[j]] = 1;
if(i%p[j]==0)
{
mu[i*p[j]] = 0;
break;
}
else mu[i*p[j]] = -mu[i];
}
}
for(int i=1;i<N;i++)
mu[i] += mu[i-1];
}
int k;
int cal(int n,int m)
{
n/=k;m/=k;
int mi = min(n,m),res = 0;
for(int l=1,r;l<=mi;l=r+1)
{
r = min(n/(n/l),(m/(m/l)));
res += (n/l)*(m/l)*(mu[r] - mu[l-1]);
}
return res;
}
signed main()
{
euler();
int t=read();
while(t--)
{
int a=read(),b=read(),c=read(),d=read();
k = read();
int res = cal(b,d) - cal(b,c-1) - cal(a-1,d) + cal(a-1,c-1);
cout<<res<<'\n';
}
return 0;
}