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的范围入手也是一样的),一个一个查找

  1. 我们先找到该数字和当前x的最大公约数,也就找到了我们要凑出的bcs的最小数据是多少,然后我们就可以去(b,d]里面找了,那么怎样才能更快的锁定这个范围呢?

  2. 我们可以直接从d,也就是最大值,去整除这个数据,因为也许并不是整除,所以再乘以minn,那就可以找到准确的倍数啦

  3. 再判断一下是不是在这个区间范围内即可。

#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;
}
posted @ 2022-10-18 21:18  Vijurria  阅读(56)  评论(0编辑  收藏  举报