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;
}