E2. Divisible Numbers (hard version)(数论)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E2. Divisible Numbers (hard version)(数论)相关的知识,希望对你有一定的参考价值。
E2. Divisible Numbers (hard version)(数论)
easy版本里是枚举x,然后找到 a b g c d ( a b , x ) \\dfracabgcd(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 \\sqrtn 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<bits/stdc++.h>
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:;
以上是关于E2. Divisible Numbers (hard version)(数论)的主要内容,如果未能解决你的问题,请参考以下文章
Gym 101102J---Divisible Numbers(反推技巧题)
Kata Daily 191012Find numbers which are divisible by given number
gym101102J Divisible Numbers(预处理)
LeetcodeLargest Divisible Subset