洛谷P1029 [NOIP2001 普及組] 最大公約數和最小公倍數問題

Tomorrowland_D發表於2024-07-23

[NOIP2001 普及組] 最大公約數和最小公倍數問題

題目描述

洛谷題目連結:https://www.luogu.com.cn/problem/P1029

輸入兩個正整數 x, y,求出滿足下列條件的 P, Q的個數:

  1. P,Q 是正整數。

  2. 要求 P, Q 以x 為最大公約數,以 y 為最小公倍數。

試求:滿足條件的所有可能的 P, Q 的個數。

輸入格式

一行兩個正整數 x, y。

輸出格式

一行一個數,表示求出滿足條件的 P, Q 的個數。

樣例 #1

樣例輸入 #1

3 60

樣例輸出 #1

4

提示

P,Q 有 4 種:

  1. 3, 60。
  2. 15, 12。
  3. 12, 15。
  4. 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;
}

程式碼解析如下:

  1. 函式 gcd(int x, int y)

    • 這是一個遞迴函式,用來計算兩個整數 ( x ) 和 ( y ) 的最大公約數(GCD)。
    • 如果 ( y ) 不為0,則遞迴地呼叫自身,傳入 ( y ) 和 ( x \mod y )。
    • 當 ( y ) 為0時,返回 ( x ),即此時的 ( x ) 就是最大公約數。
  2. 主函式 main()

    • 首先宣告瞭幾個變數:x, y, p, q, count,其中 count 用來統計滿足條件的 ( P, Q ) 的個數。
    • 輸入讀取了兩個正整數 ( x ) 和 ( y )。
  3. 迴圈部分

    • 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 )。
  4. 輸出部分

    • 輸出 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,符合示例中的期望結果。

相關文章