Codeforces - 1744E2 - Divisible Numbers (hard version)(数论 + 暴力 + 思维 、 *1900)

1744E2 - Divisible Numbers (hard version)(⇔源地址



本文参考:这位大佬的思路严格鸽的证明






tag

⇔数论、⇔暴力、⇔思维、⇔*1900。


题意

给出四个数 \(a,b,c,d\) ,请你找到任意一对 \(\{X,Y\}\) ,使得满足:

  • \(a<X\le c,b<Y\le d\)
  • \(X*Y\)\(a*b\) 的倍数。

思路

正解

由题目条件,能够得到 \(X*Y=K*a*b(1 < K)\),我们将 \(a、b\) 拆分为 \(a=x_1*y_1,b=x_2*y_2\) ,那么式子就变成 \(X*Y=K*x_1*x_2*y_1*y_2\) 。我们可以分解出 \(a、b\) 的全部因数,然后暴力枚举,代入式子中求解。

下面讨论如何代入式子中得到答案。假设我们枚举出来的因数是 \(y1、y2\) ,那么通过 \(a*b=x_1*x_2*y_1*y_2\) 可以得到 \(x_1*x_2=\dfrac{a*b}{y_1*y_2}\) 。这个时候,我们的 \(K\) 并没有参与计算,我们再拆分 \(K=k_1*k_2\) ,使得\(\left\{\begin{matrix} Y=k_1*y_1*y_2 \\ X=k_2*x_1*x_2 \end{matrix}\right.\) ,那么如何找到最小的符合条件的 \(X、Y\) 呢?

以求解 \(Y\) 为例,我们整理一下已经有的东西:已知有 \(\left\{\begin{matrix} b < Y \le d \\ Y是 y1*y2的倍数 \\ b、d、y1、y2已知 \end{matrix}\right.\) ,那么大于 \(b\) 的最小的 \(Y\) 即为 \(\left \lfloor \dfrac{b}{y_1*y_2} + 1 \right \rfloor * y_1*y_2\) ,只需要将其与 \(d\) 再做一次比较即可。\(X\) 同理。

分析正确性:使用试除法分解因数,\(\mathcal O(\sqrt N)\) ;而 \(10^9\) 以内的数字的因数最多的数量为 \(1344\) ,所以使用暴力枚举,\(\mathcal O(1344^2)\) ;最后一步暴力求解的复杂度为 \(\mathcal O(1)\) ,能够通过。

附:因数数量表

\(\pmb {n \le}\) \(\pmb {10^1}\) \(\pmb {10^2}\) \(\pmb {10^3}\) \(\pmb {10^4}\) \(\pmb {10^5}\) \(\pmb {10^6}\) \(\pmb {10^7}\) \(\pmb {10^8}\) \(\pmb {10^9}\)
\(\pmb {最大因数数量}\) 4 12 32 64 128 240 448 768 1344

后日谈

在查阅资料时,发现有很多人都是使用 \(\tt dfs\) 来替代\(a*b=x_1*x_2*y_1*y_2\) 这一步的,其本质思路是一致的,而 \(\tt dfs\) 码量较多,故这里不再单独写一份代码。这题对于数学的思维要求极高,就我而言,用式子直接计算“大于 \(b\) 的最小的 \(Y\) ”这一步可能比较难以想到,但是看过式子之后也就感觉不过如此,还是经验的问题,总的来说只要想到了正确方法,这道题就是纯打卡题了。


AC代码

点击查看代码
set<int> clac(int x) {
    set<int> num;
    for (int i = 1; i <= x / i; ++ i) {
        if (x % i == 0) num.insert(i), num.insert(x / i);
    }
    return num;
}
void Solve() {
    int a, b, c, d; cin >> a >> b >> c >> d;
    set<int> num1 = clac(a), num2 = clac(b);
    
    for (auto i : num1) {
        for (auto j : num2) {
            int x = i * j;
            int y = a * b / x;
            x = (a / x + 1) * x;
            y = (b / y + 1) * y;
            if (a < x && x <= c && b < y && y <= d) {
                cout << x << " " << y << endl;
                return;
            }
        }
    }
    cout << -1 << " " << -1 << endl;
}

错误次数:2






文 / WIDA
2022.10.24 成文
首发于WIDA个人博客,仅供学习讨论



posted @ 2022-10-24 13:17  hh2048  阅读(63)  评论(0编辑  收藏  举报