CF1967B2. Reverse Card (Hard Version) 题解 数学题

题目链接:https://codeforces.com/problemset/problem/1967/B2

题目大意:

给你两个整数 \(n\)\(m\),有满足如下条件的有序整数对 \((a, b)\) 一共有多少个:

  • \(1 \le a \le n\)\(1 \le b \le m\)
  • \(b \cdot \gcd(a,b)\)\(a + b\) 的倍数。

解题思路:

\(\gcd(a, b) = k\)\(a = Ak\)\(b = Bk\)

\((A+B) k \ |\ Bk \cdot k\)

两边同时除以 \(k\),得:

\((A+B) \ |\ B \cdot k\)

又因为 \(\gcd(A, B) = 1\),得 \(\gcd(A+B, B) = 1\)(即 \((A+B)\)\(B\) 互质),所以

\((A+B) \ | \ k\)

所以 \(A \lt k\)\(B \lt k\).

又因为

\(a = Ak \le n\),所以 \(k \le \frac{n}{A}\)

所以 \(A \lt k \le \frac{n}{A}\)\(A^2 \lt n\)

\(b = Bk \le m\),所以 \(k \le \frac{m}{B}\)

所以 \(B \lt k \le \frac{m}{B}\)\(B^2 \lt m\)

所以可以 \(O(\sqrt{nm} \log{nm})\) 的时间复杂度枚举互质的数对 \((A, B)\)(多出来的 \(log\) 是求 \(\gcd\)),

然后 \(k\) 能够取的数最大是 \(\min( \lfloor \frac{n}{A} \rfloor , \lfloor \frac{m}{B} \rfloor )\)

又因为 \((A+B) \ | \ k\)

所以满足条件的 \(k\) 的取值有 \(\lfloor \dfrac{ \min( \lfloor \frac{n}{A} \rfloor , \lfloor \frac{m}{B} \rfloor ) }{ A+B } \rfloor\) 种可能。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int T, n, m;

long long cal(int n, int m) {
    long long res = 0;
    for (int A = 1; A * A < n; A++) {
        for (int B = 1; B * B < m; B++) {
            if (__gcd(A, B) > 1) continue;
            res += min(n/A, m/B) / (A+B);
        }
    }
    return res;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        printf("%lld\n", cal(n, m));
    }
    return 0;
}
posted @ 2024-11-24 02:07  quanjun  阅读(1)  评论(0编辑  收藏  举报