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 and .
You are given positive integers with and . Find any pair of numbers and that satisfies the following conditions:
- , ,
- is divisible by .
Note that required and may not exist.
Input
The first line of the input contains a single integer , the number of test cases.
The descriptions of the test cases follow.
The only line of each test case contains four integers and .
Output
For each test case print a pair of numbers and such that is divisible by . If there are multiple answers, print any of them. If there is no such pair of numbers, then print .
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一样枚举那么必然会超时。在easy version中,我们枚举是为了得到,也就是的一个因子,而就是的另外一个因子,然后根据这个因子的倍数去找到(也是因子的倍数)。
那么我们就可以想到能否枚举的所有因子,对于其中一对因子和(),假设,,如果在区间存在的倍数,在区间存在的倍数,那么就存在一组解。判断是否在区间存在某个数的倍数的方法和easy version中的一样,就是看一下大于左端点的最小的倍数是否不超过右端点。
这里要枚举出所有的因子,感觉上好像会超时,实际上在不超过的数中,包含因子最多的那个数的因子个数为,意味着在范围内的数中,因子个数最多不超过。
因此我们可以先枚举出的因子中,所有不超过的因子,同时还要满足。然后再遍历刚才得到的所有因子,如果在区间存在的倍数,且在区间存在的倍数,那么就存在一组解。
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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16807598.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效