我有一个问题,实际上需要对欧几里得算法有所了解。问题很简单。用户通过扫描仪给出int“First”和int“Second”数字。 我们需要找到他们最大的共同除数。比过程如下所述:
现在假设第一个数字是:42,第二个是:30 - 它们是由用户给出的。 -
int x,y;
(x * First)+(y * Second)= gcd(First,Second); // X ?你?
要查找GCD,您可以使用:gcd(First,Second);代码如下:
public static int gcd(int a, int b)
{
if(a == 0 || b == 0) return a+b; // base case
return gcd(b,a%b);
}
样本输入:第一:24秒:48,输出应为x:( - 3)和y:2
样本输入:第一个:42秒:30,输出应为x:( - 2)和y:3
样本输入:第一个:35秒:05,输出应为x:(0)和y:1
(x * First) + (y * Second) = gcd(First, Second); // How can we find x and y ?
如果您能在java中显示解决方案代码,我将非常感谢,感谢您的检查!
答案 0 :(得分:3)
扩展欧几里德算法在this Wikipedia article中描述。基本算法就像这样说明(维基百科文章看起来更好):
更准确地说,标准的欧几里德算法用a和b作为 输入,包括计算序列q 1 ,..., q k 商和序列r 0 ,..., r k + 1 剩余部分
r 0 = a
r 1 = b
...
r i + 1 = r i-1 -q i r i 且0< r i + 1 < | r i |
...欧几里德分裂的主要特性是不平等 右边从r i-1 和唯一地定义r i + 1 [R <子> I 子>
当一个到达余数r k + 1 时,计算停止 这是零;最大的公约数是最后的非零 余数r k 。
扩展的欧几里德算法类似地进行,但增加了两个
定义的其他序列s 0 = 1,s 1 = 0
t 0 = 0, t 1 = 1
...
s i + 1 = s i-1 -q i s i
t i + 1 = t i-1 -q i t i
这应该很容易在Java中实现,但它所表达的数学方式可能使其难以理解。我会试着把它分解。
请注意,这可能比在递归中更容易在循环中实现。
在标准欧几里得算法中,根据r i-1 和r i 计算r i + 1 。这意味着您必须保存以前版本的 r 。这部分公式:
r i + 1 = r i-1 -q i r i 且0&lt; r i + 1 &lt; | r i |
...
只是意味着当r i-1 除以r i 时,r i + 1 将是余数。 q i 是商,你不在标准的欧几里德算法中使用,但你确实在扩展的算法中使用。因此,执行标准欧几里德算法(即计算GCD)的Java代码可能如下所示:
prevPrevR = a;
prevR = b;
while ([something]) {
nextR = prevPrevR % prevR;
quotient = prevPrevR / prevR; // not used in the standard algorithm
prevPrevR = prevR;
prevR = nextR;
}
因此,在任何时候,prevPrevR
基本上都是r i-1 ,而prevR
将是r i 。该算法计算下一个 r ,r i + 1 ,然后将基本上递增 i 的所有内容移位1。
扩展的欧几里德算法将以相同的方式完成,保存两个 s 值prevPrevS
和prevS
,以及两个 t 值{{ 1}}和prevPrevT
。我会让你弄清楚细节。
答案 1 :(得分:1)
感谢帮助我解决问题我在挖掘你的答案后解决了这个问题。对于那些希望看到代码明智的人:
public class Main
{
public static void main (String args[])
{
@SuppressWarnings("resource")
System.out.println("How many times you would like to try ?")
Scanner read = new Scanner(System.in);
int len = read.nextInt();
for(int w = 0; w < len; w++)
{
System.out.print("Please give the numbers seperated by space: ")
read.nextLine();
long tmp = read.nextLong();
long m = read.nextLong();
long n;
if (m < tmp) {
n = m;
m = tmp;
}
else {
n = tmp;
}
long[] l1 = {m, 1, 0};
long[] l2 = {n, 0, 1};
long[] l3 = new long[3];
while (l1[0]-l2[0]*(l1[0]/l2[0]) > 0) {
for (int j=0;j<3;j++) l3[j] = l2[j];
long q = l1[0]/l2[0];
for (int i = 0; i < 3; i++) {
l2[i] = (l1[i]-l2[i]*q);
}
for (int k=0;k<3;k++) l1[k] = l3[k];
}
System.out.printf("%d %d %d",l2[1],l2[2],l2[0]); // first two Bezouts identity Last One gcd
}
}
}
答案 2 :(得分:-1)
以下是我想出的代码,如果有人还在寻找的话。它在C#中,但我确信它与java类似。享受
static void Main(string[] args)
{
List<long> U = new List<long>();
List<long> V = new List<long>();
List<long> W = new List<long>();
long a, b, d, x, y;
Console.Write("Enter value for a: ");
string firstInput = Console.ReadLine();
long.TryParse(firstInput, out a);
Console.Write("Enter value for b: ");
string secondInput = Console.ReadLine();
long.TryParse(secondInput, out b);
long temp;
//Make sure that a > b
if(a < b)
{
temp = a;
a = b;
b = temp;
}
//Initialise List U
U.Add(a);
U.Add(1);
U.Add(0);
//Initialise List V
V.Add(b);
V.Add(0);
V.Add(1);
while(V[0] > 0)
{
decimal difference = U[0] / V[0];
var roundedDown = Math.Floor(difference);
long rounded = Convert.ToInt64(roundedDown);
for (int i = 0; i < 3; i++)
W.Add(U[i] - rounded * V[i]);
U.Clear();
for (int i = 0; i < 3; i++)
U.Add(V[i]);
V.Clear();
for (int i = 0; i < 3; i++)
V.Add(W[i]);
W.Clear();
}
d = U[0];
x = U[1];
y = U[2];
Console.WriteLine("\nd = {0}, x = {1}, y = {2}", d, x, y);
//Check Equation
Console.WriteLine("\nEquation check: d = ax + by\n");
Console.WriteLine("\t{0} = {1}({2}) + {3}({4})", d, a, x, b, y);
Console.WriteLine("\t{0} = {1} + {2}", d, a*x, b*y);
Console.WriteLine("\t{0} = {1}", d, (a * x) + (b * y));
if (d == (a * x) + (b * y))
Console.WriteLine("\t***Equation is satisfied!***");
else
Console.WriteLine("\tEquation is NOT satisfied!");
}
}
}