Codeforces Round #828 (Div. 3) E1. Divisible Numbers (easy version)(数学/暴力)
https://codeforces.com/contest/1744/problem/E1
题目大意:
给定a,b,c,d;
让我们选择从(a,b]中选出一个x,在(c,d]中选出一个y;
满足(x*y)/(a*b)是一个整数。
input
5
1 1 2 2
3 4 5 7
8 9 15 18
12 21 14 24
36 60 48 66
output
2 2
4 6
12 12
-1 -1
-1 -1
佬儿提醒了我暴力,可惜还是没暴力折腾出来,真是傻呀
看了他写的,顿时豁然开朗
-
因为数据范围都挺小的(1≤a<c≤10^5, 1≤b<d≤10^5),所以我们采用正确的暴力查找方法是不会爆时的
-
怎样暴力查找呢?首先我们可以知道,我们要÷的是a * b。所以我们可以先标记一下bcs==a * b,接着我们就是得找一个x * y也就是bcs的倍数
-
怎么确保x*y就是bcs的倍数呢?那么我们可以从x的范围入手(从y的范围入手也是一样的),一个一个查找
-
我们先找到该数字和当前x的最大公约数,也就找到了我们要凑出的bcs的最小数据是多少,然后我们就可以去(b,d]里面找了,那么怎样才能更快的锁定这个范围呢?
-
我们可以直接从d,也就是最大值,去整除这个数据,因为也许并不是整除,所以再乘以minn,那就可以找到准确的倍数啦
-
再判断一下是不是在这个区间范围内即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL N=500200,M=2002;
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL a,b,c,d;
cin>>a>>b>>c>>d;
LL bcs=a*b;
bool flag=false;
for(LL i=a+1;i<=c;i++)
{
LL gcd=__gcd(bcs,i);//找到和被除数的最大公约数
LL minn=bcs/gcd;//要凑出的最小的乘数
LL maxn=d/minn*minn;
if(maxn>b&&maxn<=d)
{
flag=true;
cout<<i<<" "<<maxn<<endl;
break;
}
}
if(flag==false) cout<<"-1 -1"<<endl;
}
return 0;
}