把 c 改成 d 下了两个点。
题目描述
已知正整数 a 0 , a 1 , b 0 , b 1 a_0,a_1,b_0,b_1 a0,a1,b0,b1,设某未知正整数 x x x 满足:
- x x x 和 a 0 a_0 a0 的最大公约数是 a 1 a_1 a1;
- x x x 和 b 0 b_0 b0 的最小公倍数是 b 1 b_1 b1。
求满足条件的 x x x 的个数。
Solution 1
考虑一个式子。
∀
a
,
b
∈
N
∗
\forall a,b\in\N^*
∀a,b∈N∗ 有
a
×
b
=
gcd
(
a
,
b
)
×
lcm
(
a
,
b
)
a\times b=\gcd(a,b)\times\text{lcm}(a,b)
a×b=gcd(a,b)×lcm(a,b)
枚举
gcd
(
x
,
b
0
)
\gcd(x,b_0)
gcd(x,b0),算出
x
x
x,判断
x
x
x 是否满足 1. 条件。统计答案,输出。时间复杂度
O
(
T
b
1
⋅
lg
b
1
)
O(T\sqrt{b_1}·\lg b_1)
O(Tb1⋅lgb1)。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define int long long
int T;
int a,b,c,d;
int check(int Gcd){
int x=d/c*Gcd;
if(std::__gcd(c,x)!=Gcd) return 0;
if(std::__gcd(x,a)!=b) return 0;
return 1;
}
int work(){
int sum=0;
for(int i=1;i*i<=d;++i){
if(d%i) continue;
sum+=check(i);
if(i*i!=d) sum+=check(d/i);
}
return sum;
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
printf("%lld\n",work());
}
}
Solution 2 By @zzlzk
容易想到,
∀
a
,
b
,
k
∈
N
∗
\forall a,b,k\in\N^*
∀a,b,k∈N∗ 有
gcd
(
a
,
b
)
=
k
⇔
gcd
(
a
k
,
b
k
)
=
1
\gcd(a,b)=k\quad\Leftrightarrow\quad\gcd(\frac ak,\frac bk)=1
gcd(a,b)=k⇔gcd(ka,kb)=1
化一下式子,得到
{
gcd
(
x
a
1
,
a
0
a
1
)
=
1
,
gcd
(
b
1
b
0
,
b
1
x
)
=
1.
\begin{cases}\gcd(\frac x{a_1},\frac{a_0}{a_1})=1,\\ \gcd(\frac{b_1}{b_0},\frac{b_1}x)=1.\end{cases}
{gcd(a1x,a1a0)=1,gcd(b0b1,xb1)=1.
枚举
b
1
b_1
b1 的因子,判断是不是
a
1
a_1
a1 的倍数即可。时间复杂度
O
(
T
b
1
⋅
lg
b
1
)
O(T\sqrt{b_1}·\lg b_1)
O(Tb1⋅lgb1)。
#include<cstdio>
using namespace std;
int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
int a0,a1,b0,b1;
scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
int p=a0/a1,q=b1/b0,ans=0;
for(int x=1;x*x<=b1;x++)
if(b1%x==0){
if(x%a1==0&&gcd(x/a1,p)==1&&gcd(q,b1/x)==1) ans++;
int y=b1/x;//得到另一个因子
if(x==y) continue;
if(y%a1==0&&gcd(y/a1,p)==1&&gcd(q,b1/y)==1) ans++;
}
printf("%d\n",ans);
}
return 0;
}