easy版本里是枚举x,然后找到 a b g c d ( a b , x ) \dfrac{ab}{gcd(ab,x)} gcd(ab,x)ab
显然 y ∣ g y|g y∣g。
因为 a b ∣ x y ab|xy ab∣xy,那么令 g = g c d ( a b , x ) , k 1 g = a b , k 2 g = x g=gcd(ab,x),k_1g=ab,k_2g=x g=gcd(ab,x),k1g=ab,k2g=x
k 1 ∣ k 2 y k_1|k_2y k1∣k2y, g c d ( k 1 , k 2 ) = 1 gcd(k_1,k_2)=1 gcd(k1,k2)=1。因此 k 1 ∣ y k_1|y k1∣y
枚举 k 1 k_1 k1的倍数即可找到 y y y。
那么对于hard,瓶颈在于找 x x x,但是注意到我们的关键是找 g c d ( a b , x ) gcd(ab,x) gcd(ab,x)。
那么显然我们可以枚举 a b ab ab的因子,这里我们用 n \sqrt{n} n分别枚举 a a a的因子 a ′ a' a′, b b b的因子 b ′ b' b′,注意到 1 0 9 10^9 109内最大因子个数为 1344 1344 1344。因此双重循环复杂度完全够。
我们枚举 k 1 = a ′ b ′ k_1=a'b' k1=a′b′ ,然后判两个数是否在范围内即可。
#include
using namespace std;
typedef long long ll;
ll i,j,k,n,m,t,a,b,c,d,r1,r2;
int main(){
cin>>t;
while(t--){
cin>>a>>b>>c>>d;
vector<ll> v1,v2;
for(i=1;i*i<=a;i++){
if(!(a%i)){
v1.push_back(i);v1.push_back(a/i);
}
}
for(i=1;i*i<=b;i++){
if(!(b%i)){
v2.push_back(i);v2.push_back(b/i);
}
}
for(auto i:v1)for(auto j:v2){
k=i*j;
r1=(a/k+1)*k;
if(r1>c)continue;
r2=(b/(a*b/k)+1)*(a*b/k);
if(r2>d)continue;
cout<<r1<<' '<<r2<<'\n'; goto z;
}
cout<<"-1 -1\n";
z:;
}
}