【问题标题】:Algorithm for adding two numbers to reach a value将两个数字相加以达到一个值的算法
【发布时间】:2014-12-20 16:20:23
【问题描述】:

我有一个家庭作业要求我检查任意三个数字 a,b,c 是否满足 0

为了使这成为可能,目标数字 c,必须能够以以下形式表示:

c = xa + yb

通过一些测试,我发现x和y的值不能相等,也不能同时是偶数,这样我才能达到数字c。请记住这一点,以及一些涉及 a、b 或 c 等于零的特殊情况。

有什么想法吗?

编辑: 这不是欧几里得算法,也不是丢番图方程,也许我用 c = xa + yc 的说法误导了你。即使他们应该满足这个陈述,但这对于手头的任务来说是不够的。

以a=2、b=3、c=10为例。为了达到 c,您需要在第一步中将 a 添加到 b 或 b 到 a,然后在第二步中您将得到:a = 2, b = 5 或 a = 5, b = 3 ,如果你继续这样做,你将永远无法达到 c。 Euclid 的算法将提供输出 yes,但很明显,通过将 2 和 3 相加,您无法达到 10。

【问题讨论】:

  • 我知道那些给我错误输出的 4 应该归类为“NO”,而我的代码将它们归类为“YES”。 什么 4?跨度>
  • 好像你在搜索扩展欧几里得算法(en.wikipedia.org/wiki/Extended_Euclidean_algorithm)或者中国剩余定理(en.wikipedia.org/wiki/Chinese_remainder_theorem
  • @quant 为什么选择 CRT?这只是扩展欧几里得,对吧?
  • 为什么你认为xy 不能都相等?如果c 是偶数,我认为没有理由消除这种情况,除非您忽略了原始问题的其他一些有趣特征。
  • @ajb 是的,必须有另一个条件,我似乎无法将目光放在它上面。我正在考虑优化递归,但本课程不涉及散列,因此必须有一个没有它的解决方案。如果我没有找到更简单的方法,我会尝试动态编程方法。

标签: java algorithm math


【解决方案1】:

注意: 重述问题,据我所知:假设给定非负整数 a、b 和 c。是否有可能通过执行一系列零个或多个操作a = a + bb = b + a,达到a + b == c 的点?

好的,在进一步研究之后,我认为您可以对您在问题中所做的陈述进行一些小改动:

为了使这成为可能,目标编号 c,必须能够 表示为:

c = xa + yb

其中 GCD(x,y) = 1。

(另外,xy 必须是非负数;我不确定它们是否为 0。)

您最初的观察,即 x 可能不等于 y(除非它们都是 1)并且 xy 不能都是偶数,由新条件 GCD(x,y) = 1 暗示;所以这些观察结果是正确的,但还不够强。

如果你在你的程序中使用它而不是你已经拥有的测试,它可能会使测试通过。 (我不保证任何事情。)对于更快的算法,您可以使用 cmets (和亨利的回答)中建议的扩展欧几里德算法来找到一个 x0y0;但如果 GCD(x0,y0) ≠ 1,则必须尝试其他可能性 x = x0 + nb, y = y em>0 - na,对于某些 n(可能为负数)。

我没有严格的证据。假设我们构造了所有对 (x,y) 的集合 S,使得 (1,1) 在 S em>,如果 (x,y) 在 S 中,则 (x,x+y) 和 (x+y,y) 在 S时间>。很明显 (1,n) 和 (n,1) 在 S 对于所有 n > 1 . 然后我们可以试着弄清楚,对于一些 mn > 1,这对 (m,n) 进入 S?如果 m n,只有当 (m, n-m) 已经在 S 中。如果 m > n,只有当 (m-n, n ) 已经在 S 中。无论哪种方式,当您不断从较大的数字中减去较小的数字时,您得到的本质上是欧几里得算法,这意味着您将达到您的配对 (g,g em>) 其中 g = GCD(m,n);只有当 g = 1 时,该对才在 S 中。在我看来,xy 的可能值上面等式中目标数 c 中的 em> 正是 S 中的那些。不过,这部分是基于直觉。需要做更多的工作才能使其更加严谨。

【讨论】:

  • 那个 GCD(x,y)=1 修复了它!,我现在唯一的问题是优化,因为我已经超过了其中一个执行的时间限制。很棒的工作!
【解决方案2】:

如果我们暂时忘记了 xy 应该是正数,那么方程 c = xa + yb 要么没有解,要么有无穷多个解。当 c 不是 gcd(a,b) 的倍数时,没有解。

否则,调用 gcd(a,b) = t 使用扩展欧几里得算法来找到 d 和 e,使得 t = da + eb。一个解决方案是 c = dc/t a + ec/t b。

很明显,0 = b/t a - a/t b 因此可以通过将 f 的倍数添加到方程中来找到更多解:

c = (dc + fb)/t a + (ec - af)/t b

当我们现在重新引入 x 和 y 必须为正或为零的限制时,问题变成了找到使 x = (dc + fb)/t 和 y = (ec - af)/t 均为正的 f 值或零。

如果 dc = 0 的最小 f 并查看 ec - af 是否也 >=0。

否则尝试使 ec - af >= 0 的最大 f(负数)并检查 dc + fb >= 0。

【讨论】:

    【解决方案3】:
    import java.util.*;
    import java.math.BigInteger;
    
    public class Main
    {
        private static boolean result(long a, long b, long c)
        {
            long M=c%(a+b);
            return (M%b == 0) || (M%a == 0);
        }
    }
    

    Idea:c=xa+by,因为 x 或 y 更大,我们可以将后一个方程写成以下两种形式之一: c=x(a+b)+(y-x)b, c=y(a+b)+(x-y)a 取决于谁更大,因此通过每次将 c 减少 a+b , c 最终变为: c=(y-x)b 或 c=(x-y)b,因此 c%b 或 c%a 将计算为 0。

    【讨论】:

    • 看起来您编写了一个计算c % (a + b) 的递归函数。然后,一旦计算出 M = c % (a + b),如果 M 可被 ab 整除,则返回 true。我不认为这是正确的答案,而且无论如何,委婉地说,这不是递归的好方法。
    • 这只告诉我线性方程是否有解。但是,正如我在问题描述中所述并在我的一个 cmets 中解释的那样,通过将 a 和 b 相加来确定我是否可以达到数字 c 是不够的。
    • @ajb 它实际计算 c/(a+b) 然后 M=c/(a+b) 被测试。无论如何,为什么不好好利用递归呢?
    • @user2980055 为什么还不够?
    • 如果c >= a+b,那么resultc-a-b调用自己,然后c-2a-2b,然后c-3a-3b等等,直到c小于a + b。当然ab 在每个递归调用中都是相同的。结果是最后一个c 等于原来的c % (a + b)。如果你不相信我,你自己试试。它不能很好地使用递归的原因是因为您正在使用递归来计算可以用一个表达式计算的东西。
    猜你喜欢
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 2015-12-29
    • 1970-01-01
    相关资源
    最近更新 更多