传送门
题目大意
问闭区间 [ l , r ] [l,r] [l,r]内存在多少对 a , b a,b a,b满足 g c d ( a , b ) = x , l c m ( a , b ) = y gcd(a,b)=x,lcm(a,b)=y gcd(a,b)=x,lcm(a,b)=y;
思路
设
a
=
n
∗
x
,
b
=
m
∗
x
a=n*x,b=m*x
a=n∗x,b=m∗x
y
=
a
∗
b
x
y=\frac{a*b}{x}
y=xa∗b
那么
a
∗
b
=
x
∗
y
a*b=x*y
a∗b=x∗y
y
x
=
a
∗
b
x
2
=
n
∗
x
∗
m
∗
x
x
2
=
n
∗
m
\frac{y}{x}=\frac{a*b}{x^2}=\frac{n*x*m*x}{x^2}=n*m
xy=x2a∗b=x2n∗x∗m∗x=n∗m
y
/
x
=
n
∗
m
y/x=n*m
y/x=n∗m
找到满足的
n
,
m
n,m
n,m即可,因为
n
∗
m
=
y
/
x
n*m=y/x
n∗m=y/x,时间复杂度
l
o
g
(
1
e
9
)
log(1e9)
log(1e9)
代码
ll l,r,x,y;
ll check(int a,int b){
if(a*x>=l&&a*x<=r&&b*x>=l&&b*x<=r)return 1;
return 0;
}
ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}
int main(){
scanf("%lld%lld%lld%lld",&l,&r,&x,&y);
if(y%x){//x不是y的因数,一定找不到
puts("0");
return 0;
}
ll tmp=y/x;
int cnt=0;
for(int i=1;i*i<=tmp;i++){
if(tmp%i==0&&check(tmp/i,i)&&gcd(i,tmp/i)==1){
if(i==tmp/i)cnt++;
else cnt+=2;
}
}
printf("%d\n",cnt);
}