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