D2. Reverse Card (Hard Version)
题意
给定两个正整数 n , m n,m n , m ,计算满足条件的有序数对 ( a , b ) (a,b) ( a , b ) 的数量:
1 ≤ a ≤ n 1 \le a \le n 1 ≤ a ≤ n ,1 ≤ b ≤ m 1 \le b \le m 1 ≤ b ≤ m 。
b ⋅ gcd ( a , b ) b\cdot \gcd(a,b) b ⋅ g cd( a , b ) 是 a + b a+b a + b 的倍数。
输入
每个测试包含多个测试用例。第一行包含测试用例数量 t t t ,满足 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1 ≤ t ≤ 1 0 4 。
每个测试用例包含两个整数 n , m n,m n , m ,满足 1 ≤ n , m ≤ 2 ⋅ 1 0 6 1 \le n,m \le 2\cdot 10^6 1 ≤ n , m ≤ 2 ⋅ 1 0 6 。
所有测试用例中 n n n 和 m m m 的总和不超过 2 ⋅ 1 0 6 2\cdot 10^6 2 ⋅ 1 0 6 。
输出
对每个测试用例输出一个整数,表示有效数对数量。
分析
设 d = gcd ( a , b ) d=\gcd(a,b) d = g cd( a , b ) ,并令:
a = p d , b = q d a=pd, \quad b=qd
a = p d , b = q d
其中 gcd ( p , q ) = 1 \gcd(p,q)=1 g cd( p , q ) = 1 。原条件可以写成:
b ⋅ gcd ( a , b ) = k ( a + b ) b\cdot\gcd(a,b)=k(a+b)
b ⋅ g cd( a , b ) = k ( a + b )
代入后得到:
q d 2 = k ( p + q ) d qd^2 = k(p+q)d
q d 2 = k ( p + q ) d
也就是:
q d = k ( p + q ) qd = k(p+q)
q d = k ( p + q )
因为 gcd ( p , q ) = 1 \gcd(p,q)=1 g cd( p , q ) = 1 ,所以 gcd ( p + q , q ) = 1 \gcd(p+q,q)=1 g cd( p + q , q ) = 1 ,从而可以推出 p + q p+q p + q 需要整除 d d d 。
枚举互质的 p , q p,q p , q ,它们对答案的贡献为:
⌊ min ( ⌊ n / p ⌋ , ⌊ m / q ⌋ ) p + q ⌋ \left\lfloor \frac{\min(\lfloor n/p\rfloor,\lfloor m/q\rfloor)}{p+q} \right\rfloor
⌊ p + q min ( ⌊ n / p ⌋ , ⌊ m / q ⌋ ) ⌋
因此可以枚举 p ≤ n p\le \sqrt n p ≤ n 、q ≤ m q\le \sqrt m q ≤ m ,并用 gcd ( p , q ) = 1 \gcd(p,q)=1 g cd( p , q ) = 1 判断是否有效。
代码
void solve() {
int n, m;
cin >> n >> m;
int ans = 0;
for (int p = 1; p <= n / p; p++) {
for (int q = 1; q <= m / q; q++) {
if (__gcd(p, q) == 1) {
ans += min(n / p, m / q) / (p + q);
}
}
}
cout << ans << "\n";
}