CF1967B2. Reverse Card (Hard Version) 題解 數學題

quanjun發表於2024-11-24

題目連結: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;
}

相關文章