查找指定范围内的最大公约数 (GCD)


问题要求我们找到位于给定范围内的最大公约数 (GCD)。我们将得到两个正整数 x 和 y,以及两个整数 p 和 q,它们表示范围 [p,q]。我们需要找出 x 和 y 的最大公约数,并且这个最大公约数必须落在这个范围 [p,q] 内。最大公约数 (GCD),在数学中也称为最大公因数,是能够同时整除两个给定正整数的最大正整数。给定的整数不能为零。对于任意两个正整数 x 和 y,它表示为 gcd(x,y)。

例如,我们得到两个正整数 6 和 9。它们的最大公约数 gcd(6,9) 为 3,因为它是能够同时整除这两个数的最大数。

但是在这个问题中,我们需要找到两个给定正整数的最大公约数,并且这个最大公约数必须落在指定的范围内。让我们用例子来理解这个问题。我们将得到 4 个数字作为输入:x 和 y(用于求这两个数的最大公约数),以及两个数字表示最大公约数的范围,即 [p,q]。

输入:x=8,y=12,p=1,q=3

输出 : 2

解释 – 给定两个数 x 和 y 的最大公约数是 4。但是 4 不在范围 [1,3] 内。在这个范围内最大的公约数是 2,这就是我们需要的输出。

输入:x=17,y=15,a=5,b=10

输出 : -1

解释 – 数 17 和 15 的最大公约数是 1。由于 1 不在给定范围 [5,10] 内。当给定范围内没有公约数时,我们需要输出 -1。

算法

我们将用来解决这个问题的算法非常简单,并且与数学相关。首先,我们将找到数 x 和 y 的最大公约数 (GCD)。在 C++ 中,有一个名为 gcd() 的内置函数,它返回两个数的最大公约数作为输出。

语法

int divisor=gcd(x,y);

我们也可以使用高效的欧几里得算法来查找两个数的最大公约数。两者的时间复杂度相同,即 O(log(min(x,y)))。

现在,我们可以根据简单的算术定律得出结论:能够整除两个数的最大公约数的数,也能同时整除这两个数本身。因此,从 i=1 迭代到 sqrt(gcd(x,y)) 将帮助我们获得该数的所有公约数。

然后,检查从 1 到 sqrt(gcd(x,y)) 的每一个 i 是否整除 gcd(x,y)。如果 i 整除 gcd(x,y),那么我们可以说 gcd(x,y)/i 也是 gcd 的约数,因此它也是数 x 和 y 的公约数。

让我们用一个例子来理解这个概念。假设 x 和 y 为 32 和 48。gcd(18,27) 为 16。在这种情况下,我们将从 i=1 迭代到 i<=4,即 sqrt(16)。让我们考虑 i=2。这里 i 整除 gcd(18,27),即 16/2 等于 8。因此,gcd(x,y)/i 也将整除 gcd(x,y) 得到 i。

注意 – 如果一个数 n 除以任何数 x 得到 y,可以表示为 $\frac{n}{x}\:=\:y$,那么 y 也将整除 n 得到 x $(x\:\times\:y\:=\:n)$。

这个算法可能是解决这个问题最有效的方法。遵循此算法时,我们将不断检查公约数是否在范围 [a,b] 内。如果在范围内,我们将使用 **max()** 函数在一个变量中更新约数,以便获得范围内最大的公约数。

max() 函数的语法

int m = max(a,b);

它返回 a 和 b 中较大的值。

方法

以下是我们将遵循的方法:

  • 初始化一个函数来计算位于给定范围内的最大公约数。

  • 计算两个给定正数 x 和 y 的最大公约数。

  • 初始化一个名为 ans 的变量,其值为 -1。

  • 从 i=1 迭代到 i<=sqrt(gcd(x,y)),并不断检查 i 是否整除 gcd(x,y)。

  • 如果 (gcd(x,y)%i)=0,则检查 i 是否在范围 [a,b] 内,如果在范围内,则使用 max() 函数将其存储在 ans 中,以便我们获得范围内最大的公约数。

  • 还要检查 gcd/i 是否在范围内,如果在范围内,则再次使用 max() 函数更新 ans 的值。

  • 完成 for 循环中的所有迭代后返回 ans。

示例

C++ 中该方法的实现:

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;

// to calculate gcd of two numbers using Euclidean algorithm
int gcd(int a, int b){
   if(a == 0)
   return b;
   return gcd(b % a, a);
}

//function to calculate greatest common divisor in the given range [a,b]
int build(int x, int y, int a, int b) {

   //using C++ inbuilt library to calculate gcd of given numbers
   int z = gcd(x, y); //we can use euclidean algorithm too as an alternative
   int ans = -1; //storing -1 for the case when no common divisor lies in the range
   for(int i = 1; i<=sqrt(z); i++) { //iterating until sqrt(z) because either of two factors
      //of a number must be less than square root of the number
      if(z % i == 0) {
         if(i >= a && i <= b) //checking it i lies in the range
         ans = max(ans, i); //storing maximum value
         if((z / i) >= a && (z / i) <= b)
         ans = max(ans, z / i);
      }
   }
   return ans;
}
int main() {
   int x, y, a, b;
   x=24, y=42, a=3, b=9;
   cout << build(x, y, a, b) <<" is the gcd that lies in range ["<<a<<","<<b<<"]"<<endl;
   return 0;
}

输出

6 is the gcd that lies in range [3,9]

时间复杂度:O(log(min(x,y)) + sqrt(z)),其中 z 是两个数 x 和 y 的最大公约数。

空间复杂度:O(1),因为没有使用额外的空间。

结论

我们讨论了解决问题的方法,即查找位于范围 [a,b] 内的两个数的最大公约数。这就是我们如何使用各种不同函数在 C++ 中解决上述问题。

我希望您觉得这篇文章有帮助,并能清除您对该问题的全部概念。

更新于:2023年3月16日

479 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告