洛谷P1072 Hankson的趣味題

wisdom_grass發表於2020-11-04

傳送門

solution:

很妙的數學推導題
易知,一般的,令 k = gcd ⁡ ( a , b ) k = \gcd(a, b) k=gcd(a,b),則 gcd ⁡ ( a / k , b / k ) = 1 \gcd(a / k, b / k) = 1 gcd(a/k,b/k)=1
那麼將 gcd ⁡ ( x , a 0 ) = a 1 \gcd(x, a_0) = a_1 gcd(x,a0)=a1轉化為 gcd ⁡ ( x / a 1 , a 0 / a 1 ) = 1 \gcd(x / a_1, a_0 / a_1) = 1 gcd(x/a1,a0/a1)=1
又由 b 1 = lcm ⁡ ( x , b 0 ) = x ∗ b 0 / gcd ⁡ ( x , b 0 ) b_1 = \operatorname{lcm}(x, b_0) = x * b_0 / \gcd(x, b_0) b1=lcm(x,b0)=xb0/gcd(x,b0)知,
gcd ⁡ ( x , b 0 ) = x ∗ b 0 / b 1 \gcd(x, b_0) = x * b_0 / b_1 gcd(x,b0)=xb0/b1。令 k 1 = gcd ⁡ ( x , b 0 ) k_1 = \gcd(x, b_0) k1=gcd(x,b0)
gcd ⁡ ( x / k 1 , b 0 / k 1 ) = 1 \gcd(x / k_1, b_0 / k_1) = 1 gcd(x/k1,b0/k1)=1
化簡得 gcd ⁡ ( b 1 / b 0 , b 1 / x ) = 1 \gcd(b_1 / b_0, b_1 / x) = 1 gcd(b1/b0,b1/x)=1 ---------------------------------②
由①②式的限制,可以設計出演算法:
列舉 b 1 b_1 b1的因數 i i i,判斷 i i i是否是 a 1 a_1 a1的倍數,並且是否滿足①②式子。
若滿足則 i i i是符合題目要求的數之一。
時間複雜度O( b 1 \sqrt{b_1} b1 )。

code:

#include <iostream>
#include <cstdio>
using namespace std;

typedef long long LL;
int T;
LL a_0, a_1, b_0, b_1;

LL GCD(LL A, LL B) {
	if(!B) return A;
	return GCD(B, A % B);
}
int main() {
	#ifdef test
		freopen("test.txt", "r", stdin);
	#endif
	cin >> T;
	int ans = 0;
	while(T--) {
		ans = 0;
		cin >> a_0 >> a_1 >> b_0 >> b_1;
		for(int i = 1; i * i <= b_1; i++) { // 因子i
			if(b_1 % i) continue;
			if(i % a_1 == 0 && GCD(i / a_1, a_0 / a_1) == 1 && GCD(b_1 / b_0, b_1 / i) == 1)
				ans++;
			int h = b_1 / i; // 大於根號N的因子。
			if(h == i) continue; // 特判當i等於h的情況,此時兩個因子重複不能計入答案。
			if(h % a_1 == 0 && GCD(h / a_1, a_0 / a_1) == 1 && GCD(b_1 / b_0, b_1 / h) == 1)
				ans++;
		}
		cout << ans << endl;
	}
	return 0;
}

相關文章