[NOIP2001 普及組] 最大公約數和最小公倍數問題
題目描述
洛谷題目連結:https://www.luogu.com.cn/problem/P1029
輸入兩個正整數 x, y,求出滿足下列條件的 P, Q的個數:
-
P,Q 是正整數。
-
要求 P, Q 以x 為最大公約數,以 y 為最小公倍數。
試求:滿足條件的所有可能的 P, Q 的個數。
輸入格式
一行兩個正整數 x, y。
輸出格式
一行一個數,表示求出滿足條件的 P, Q 的個數。
樣例 #1
樣例輸入 #1
3 60
樣例輸出 #1
4
提示
P,Q 有 4 種:
- 3, 60。
- 15, 12。
- 12, 15。
- 60, 3。
對於 100% 的資料,2<=x,y<=10^5.
【題目來源】
NOIP 2001 普及組第二題
思路:
我們可以列舉最大公倍數y的所有因子,然後檢查每一對因子的最小公倍數是不是x即可。最後算出所有的對數。
這段程式碼是用來解決題目中要求的問題:找出滿足條件的 ( P, Q ) 的個數,使得它們的最大公約數是 ( x ),最小公倍數是 ( y )。
AC程式碼如下:
#include<iostream>
using namespace std;
int gcd(int x, int y)
{
return y ? gcd(y, x % y) : x;
}
int main()
{
int x, y;
int count = 0;
cin >> x >> y;
for (int k = 1; k <= y / k; k++) {
if (y % k == 0) {
if (gcd(k, y / k * x) == x) count++;
if (k != y / k) {
if (gcd(y / k , k * x) == x) count++;
}
}
}
cout << count;
return 0;
}
程式碼解析如下:
-
函式
gcd(int x, int y)
:- 這是一個遞迴函式,用來計算兩個整數 ( x ) 和 ( y ) 的最大公約數(GCD)。
- 如果 ( y ) 不為0,則遞迴地呼叫自身,傳入 ( y ) 和 ( x \mod y )。
- 當 ( y ) 為0時,返回 ( x ),即此時的 ( x ) 就是最大公約數。
-
主函式
main()
:- 首先宣告瞭幾個變數:
x, y, p, q, count
,其中count
用來統計滿足條件的 ( P, Q ) 的個數。 - 輸入讀取了兩個正整數 ( x ) 和 ( y )。
- 首先宣告瞭幾個變數:
-
迴圈部分:
for (int k = 1; k <= y / k; k++)
:從 ( k = 1 ) 開始,遍歷到 ( k ) 小於等於 ( sqrt(y) )。if (y % k == 0)
:檢查 ( k ) 是否是 ( y ) 的因子。- 如果是 ( y ) 的因子,說明 ( y ) 可以分解為 (y=k*(y/k))。
if (gcd(k, y / k * x) == x) count++
和if (gcd(y / k, k * x) == x) count++
:- 分別檢查 (k,y/k*x)與(y/k,k/x) 這兩對是否滿足條件。
- 即檢查它們的最大公約數是否等於 ( x )。
-
輸出部分:
- 輸出
count
,即滿足條件的 ( P, Q ) 的個數。
- 輸出
這段程式碼利用了數學上的性質,透過分解 ( y ) 的因子來檢查每一對 ( P, Q ) 是否滿足條件,使用了最大公約數函式 gcd
來驗證條件。這種方法相比直接遍歷所有可能的 ( P, Q ) 組合更加高效。
示例解析
對於輸入 3 60
,程式會計算:
- ( x = 3 ),( y= 60 )。
- 遍歷 ( k ) 從 1 到 ( sqrt(60)):
- 找到 ( k = 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 ) 是 ( 60 ) 的因子。
- 對每個 ( k ),檢查 ( (k, 60/k 3) ) 和 ( (60/k, k* 3) ) 是否滿足條件。
- 統計滿足條件的 ( P, Q ) 的個數。
輸出結果為 4
,符合示例中的期望結果。