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 yg

因为 a b ∣ x y ab|xy abxy,那么令 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 k1k2y g c d ( k 1 , k 2 ) = 1 gcd(k_1,k_2)=1 gcd(k1,k2)=1。因此 k 1 ∣ y k_1|y k1y

枚举 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=ab ,然后判两个数是否在范围内即可。

#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

LeetCode Largest Divisible Subset

Largest Divisible Subset