找出具有给定GCD值的数字

4
我正在研究用于查找数字最大公约数的欧几里得算法。它可以用于查找给定两个数字的GCD。然而,如果我已知一个数字与多个其他数字的GCD,例如第一个数字与另外三个数字(包括它本身)的GCD,即:

给定:a与a的GCD,a与b的GCD,a与c的GCD,a与d的GCD。 其他数字也是这样,即b与a的GCD,b与b的GCD,......

那么,我该如何找到各自的数字呢?我知道GCD(a,a)= a本身,但问题在于,给定的个别GCD是以随机顺序排列的,因此,我不知道哪个输入数字是哪两个数字的GCD。在这种情况下,我该如何找到各自的数字?

这是我的GCD代码:

int gcd(int a,int b)
{
   if(b==0)
   {
       return a;
   }
   return gcd(b,a%b);
}

例如:假设给定的输入为,

3 1 3 1 4 2 2 3 6
3 //(total numbers we have to find in original array)

那么输出应该是3 4 6。因为如果你逐对地计算这些数字的最大公约数(共9对,因此输入9个数字),我们就能得到上述输出。
Explanation: 3 -> GCD of (3,3)
1 -> GCD of (3,4)
3 -> GCD of (3,6)
1 -> GCD of (4,3)
4 -> GCD of (4,4)
2 -> GCD of (4,6)
6 -> GCD of (6,6)
3 -> GCD of (6,3)
2 -> GCD of (6,4)

因此,我必须找到最大公约数为输入值的数字。因此,(3,4,6)就是这些数字。

请提供一个输入的例子,并说明你期望得到什么输出。 - Vaughn Cato
查找中国剩余定理。 - Alan Stokes
1
不确定这与C++有什么关系。 - Lightness Races in Orbit
我猜这个太难了。你知道,1 + 4 = 5,2 + 3 = 5,但这并不意味着1 = 2或3 = 4。我的意思是两个不同的数对的最大公约数可能相同,所以很难找到这些数字。我认为一些限制可能有所帮助,但是......为此设计一个算法很难想到。 - Jeet Parekh
不,问题是我可以输出这个可能的任何组合之一。 - rohansingh
显示剩余6条评论
4个回答

3
我认为您可以通过以下步骤完成此操作:
  1. 找到并删除最大的数字,这是原始数字之一
  2. 计算刚刚在步骤1中发现的数字与先前在步骤1中找到的所有数字的gcd。
  3. 从gcd的输入数组中删除这些计算出的gcd(严格来说,删除每个gcd的2个副本)
  4. 重复此过程直到找到所有数字
关键是,仅当第1步中找到的最大数字x不是原始数字之一时,才会出现问题。但是,这只能发生在x是两个其他数字的gcd的情况下。这些其他数字必须至少与x一样大,但是所有这样的gcd都已在步骤3中删除。因此,x始终是原始数字之一。

1
如果输入的第二行是1,那么输入的第一行只有一个数字,并且由于您观察到gcd(a,a)= a,因此a的值将是输入的第一行上的任何值。
如果输入的第二行的值大于1,则可以使用以下观察结果来缩小问题。给定正整数ab,我们知道gcd(a,b)<= a = gcd(a,a)gcd(a,b)<= b = gcd(b,b)始终成立。因此,我们可以得出结论,第一行输入中最大的两个数字都必须是基本数字集的一部分。最大的两个数字可能相等,但在您的示例中,它们是46,并且它们不相等。
如果要查找的数字超过两个,我们将最大的两个称为ab。由于我们现在知道了ab的值,我们可以计算gcd(a,b)并从考虑作为输入数字之一的那个值中删除两个出现。 我们删除两个出现是因为gcd(a,b)= gcd(b,a)都在输入数字列表中。然后使用类似的逻辑,我们得出结论,在删除abgcd(a,b)gcd(b,a)之后剩余的最大数字必须是其中一个输入数字。

洗涤,漂洗,重复。


1
非常好。因此,这可以简化为当输入不为空时{将输入中最大的数字添加到输出中;从输入中删除新已知的gcd结果} - Vaughn Cato

1
这其实很简单:
  • 计算数组中每个不同数字出现的次数
  • 如果该次数为奇数,则该数字是你集合中的一个数字
  • 如果该次数为偶数,则该数字不是你集合中的数字。

原因在于当x!= y时,gcd(x,y)= gcd(y,x),那个数字将在数组中出现两次。只有来自gcd(x,x)的值才会出现一次,导致该特定值的数量为奇数。


3
假设基础集合中没有重复数字。如果基础集合是3 3 2,那么输入的第一行将类似于1 3 3 1 3 3 1 1 2,此方法只能找到基础集合中的2。 - Evan VanderZee
@EvanVanderZee 很好的观察 - Punit Vara

-1

正如我们在这里看到的,对于每个数字与其他数字,都会计算出一个最大公约数并添加到现有列表中,因此最终我们将拥有原始n个数字的n * n个数字。因此,可以使用相同的方法来反向查找原始数字

  1. 按降序对列表进行排序。
  2. 收集前n^(0.5)个数字,这将是我们的答案。

以您的示例为例

3 1 3 1 4 2 2 3 6

排序后 = 6 4 3 3 3 2 2 1 1

n的值= 9

n^(0.5)的值= 3

选择前3个数字6、4和3。这就是我们的答案


这并不总是正确的。以这个例子为例:A = [46, 45, 40, 31, 5, 5, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].... |A|^(0.5) = 5,因此前5个元素是[46,45,40,31,5],但实际答案应该是:[46,45,40,31,1]。 - Vikas Bansal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接