E2. Divisible Numbers (hard version)

E2. Divisible Numbers (hard version)

This is an hard version of the problem. The only difference between an easy and a hard version is the constraints on a,b,c and d.

You are given 4 positive integers a,b,c,d with a<c and b<d. Find any pair of numbers x and y that satisfies the following conditions:

  • a<xc , b<yd,
  • xy is divisible by ab.

Note that required x and y may not exist.

Input

The first line of the input contains a single integer t (1t10), the number of test cases.

The descriptions of the test cases follow.

The only line of each test case contains four integers a,b,c and d (1a<c109,1b<d109).

Output

For each test case print a pair of numbers a<xc and b<yd such that xy is divisible by ab. If there are multiple answers, print any of them. If there is no such pair of numbers, then print -1 -1.

Example

input

复制代码
10
1 1 2 2
3 4 5 7
8 9 15 18
12 21 14 24
36 60 48 66
1024 729 373248 730
1024 729 373247 730
5040 40320 40319 1000000000
999999999 999999999 1000000000 1000000000
268435456 268435456 1000000000 1000000000
复制代码

output

复制代码
2 2
4 6
12 12
-1 -1
-1 -1
373248 730
-1 -1
15120 53760
-1 -1
536870912 536870912
复制代码

 

解题思路

  参考easy version

  如果像easy version一样枚举x那么必然会超时。在easy version中,我们枚举x是为了得到gcd(x,ab),也就是ab的一个因子,而abgcd(ab,x)就是ab的另外一个因子,然后根据这个因子的倍数去找到yx也是因子gcd(x,ab)的倍数)。

  那么我们就可以想到能否枚举ab的所有因子,对于其中一对因子abab=ab),假设axby,如果在区间[a+1,c]存在a的倍数,在区间[b+1,d]存在b的倍数,那么就存在一组解。判断是否在区间存在某个数的倍数的方法和easy version中的一样,就是看一下大于左端点的最小的倍数是否不超过右端点。

  这里要枚举出所有ab的因子,感觉上好像会超时,实际上在不超过109的数中,包含因子最多的那个数的因子个数为1344,意味着在1018范围内的数中,因子个数最多不超过13442

  因此我们可以先枚举出ab的因子中,所有不超过c的因子t,同时t还要满足abtd。然后再遍历刚才得到的所有因子d,如果在区间[a+1,c]存在d的倍数,且在区间[b+1,d]存在abd的倍数,那么就存在一组解。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 LL a, b, c, d;
 7 LL m;
 8 unordered_map<int, int> mp;
 9 vector<pair<int, int>> p;
10 vector<int> ds;
11 
12 void divide(int x) { 
13     for (int i = 2; i <= x / i; i++) {
14         while (x % i == 0) {
15             mp[i]++;
16             x /= i;
17         }
18     }
19     if (x > 1) mp[x]++;
20 }
21 
22 void dfs(int u, LL prod) {
23     if (prod > c) return;    // 因子超过[a+1, c]这个范围 
24     if (u == p.size()) {
25         if (m / prod <= d) ds.push_back(prod);    // 另外一个因子超过[b+1, d]这个范围 
26         return;
27     }
28     LL t = 1;
29     for (int i = 0; i <= p[u].second; i++) {
30         dfs(u + 1, prod * t);
31         t *= p[u].first;
32     }
33 }
34 
35 void solve() {
36     mp.clear(), p.clear(), ds.clear();
37     cin >> a >> b >> c >> d;
38     m = a * b;
39     divide(a), divide(b);    // 质因数分解
40     for (auto &it : mp) {
41         p.push_back(it);
42     }
43     dfs(0, 1);    // 求a*b的因子 
44     for (int i = 0; i < ds.size(); i++) {
45         int x = ds[i], y = m / x;
46         x = (a / x + 1) * x, y = (b / y + 1) * y;
47         if (x <= c && y <= d) {    // 在区间范围内存在因子倍数 
48             printf("%d %d\n", x, y);
49             return;
50         }
51     }
52     printf("-1 -1\n");
53 }
54 
55 int main() {
56     int t;
57     scanf("%d", &t);
58     while (t--) {
59         solve();
60     }
61     
62     return 0;
63 }
复制代码

 

参考资料

  Codeforces Round #828 (Div. 3) Editorial:https://codeforces.com/blog/entry/108101

posted @   onlyblues  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示