题目
求 a ≤ x ≤ b , c ≤ y ≤ d a\leq x\leq b,c\leq y\leq d a≤x≤b,c≤y≤d中 g c d ( x , y ) = k gcd(x,y)=k gcd(x,y)=k的个数
分析
其实只要做了洛谷 3455就会理解很多
蒟蒻的题解
然后这道题可以用前缀和表达出来
T
o
t
a
l
A
n
s
=
A
n
s
(
b
,
d
)
−
A
n
s
(
a
−
1
,
d
)
−
A
n
s
(
b
,
c
−
1
)
+
A
n
s
(
a
−
1
,
c
−
1
)
TotalAns=Ans(b,d)-Ans(a-1,d)-Ans(b,c-1)+Ans(a-1,c-1)
TotalAns=Ans(b,d)−Ans(a−1,d)−Ans(b,c−1)+Ans(a−1,c−1)
那么如何求一个呢
f
(
k
)
=
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
k
]
f(k)=\sum_{i=1}^{n}\sum_{j=1}^{m} [gcd(i,j)=k]
f(k)=i=1∑nj=1∑m[gcd(i,j)=k]
F
(
d
)
=
∑
k
∣
d
f
(
k
)
=
⌊
n
d
⌋
⌊
m
d
⌋
F(d)=\sum_{k|d}f(k)=\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor
F(d)=k∣d∑f(k)=⌊dn⌋⌊dm⌋
根据莫比乌斯反演可以得到
f
(
k
)
=
∑
k
∣
d
μ
(
⌊
d
k
⌋
)
×
F
(
d
)
f(k)=\sum_{k|d}\mu(\lfloor\frac{d}{k}\rfloor)\times F(d)
f(k)=k∣d∑μ(⌊kd⌋)×F(d)
A
n
s
=
∑
k
∣
d
μ
(
⌊
d
k
⌋
)
×
F
(
d
)
Ans=\sum_{k|d}\mu(\lfloor\frac{d}{k}\rfloor)\times F(d)
Ans=k∣d∑μ(⌊kd⌋)×F(d)
枚举
⌊
d
k
⌋
\lfloor\frac{d}{k}\rfloor
⌊kd⌋,那么也就是
A
n
s
=
∑
i
=
1
m
i
n
{
n
,
m
}
μ
(
i
)
×
⌊
n
i
∗
d
⌋
×
⌊
m
i
∗
d
⌋
Ans=\sum_{i=1}^{min\{n,m\}}\mu(i)\times\lfloor\frac{n}{i*d}\rfloor\times\lfloor\frac{m}{i*d}\rfloor
Ans=i=1∑min{n,m}μ(i)×⌊i∗dn⌋×⌊i∗dm⌋
接着用整除分块一波推就好了
代码
#include <cstdio>
#define rr register
#define min(a,b) ((a)<(b))?(a):(b)
#define N 50000
using namespace std;
typedef unsigned uit;
uit cnt,mu[N+1],v[N+1],prime[N+1];
inline signed iut(){
rr uit ans=0; rr char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
inline void iiiii(){//线性筛莫比乌斯函数
mu[1]=1;
for (rr uit i=2;i<=N;++i){
if (!v[i]) v[i]=i,prime[++cnt]=i,mu[i]=-1;
for (rr uit j=1;j<=cnt&&prime[j]*i<=N;++j){
v[i*prime[j]]=prime[j];
if (i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
for (rr uit i=2;i<=N;++i) mu[i]+=mu[i-1];
}
inline void print(uit ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed answ(uit n,uit m,uit k){
rr uit ans=0,t=min(n,m);
for (rr uit l=1,r;l<=t;l=r+1){
r=min(n/(n/l),m/(m/l));//确定区间
ans+=(n/l/k)*(m/l/k)*(mu[r]-mu[l-1]);//计算答案
}
return ans;
}
signed main(){
iiiii();
for (rr uit t=iut();t;--t){
rr uit a=iut(),b=iut(),c=iut(),d=iut(),k=iut();
rr uit ans=answ(b,d,k)+answ(a-1,c-1,k)-answ(b,c-1,k)-answ(a-1,d,k);
if (ans) print(ans); else putchar(48); putchar(10);
}
return 0;
}