在Java中,我被指派比较一对3个正双变量,同时忽略它们的顺序。我做了以下事情:
if ((a1 == a2 && b1 == b2 && c1 == c2) ||
(a1 == a2 && b1 == c2 && c1 == b2) ||
(a1 == b2 && b1 == a2 && c1 == c2) ||
(a1 == b2 && b1 == c2 && c1 == a2) ||
(a1 == c2 && b1 == a2 && c1 == b2) ||
(a1 == c2 && b1 == b2 && c1 == a2))
// if true
我从老师那里听说有一种数学方法可以比较这对3个数字。
到目前为止,我试着将它们的加法、减法和2的幂和进行比较,但我总是发现这两种情况不同,而且这种说法是正确的。
有什么想法吗?
编辑:
我已经寄出了作业,老师说我的答案是正确的。我问是出于好奇。
TL;DR
比较每个三元组的和、每个三元组乘积以及每个三元组所有可能组合的乘积之和。
Nitty Gritty
根据代数基本定理,对于N次多项式,我们必须有N个根。
利用这个事实,我们让我们的零是a1, a2, and a3
。现在,我们找到这个多项式的系数。
(x - a1) * (x - a2) * (x - a3)
(x^2 - (a1 + a2) * x + a1a2) * (x - a3)
x^3 - (a1 + a2) * x^2 + (a1a2) * x - a3 * x^2 + (a1a3 + a2a3) * x - a1a2a3
x^3 + (-1 * (a1 + a2 + a3)) * x^2 + (a1a2 + a1a3 + a2a3) * x + (-1 * a1a2a3)
如果两个多项式是等价的,它们必须具有相同的根(同样根据FTA(。因此,我们所需要做的就是比较生成的多项式的系数。
所以,如果
(-1 * (a1 + a2 + a3) == (-1 * (b1 + b2 + b3))
---equivalently---
a1 + a2 + a3 == b1 + b2 + b3
和
(a1a2 + a1a3 + a2a3) == (b1b2 + b1b3 + b2b3)
和
-1 * a1a2a3 == -1 * b1b2b3
---equivalently---
a1a2a3 == b1b2b3
从而得出三重态a1, a2, a3
和b1, b2, b3
是等价的。
值得吗
从实际的角度来看,让我们看看这是否真的比OP所示的暴力检查更有效
第一次检查:求和比较。这需要总共4个加法和1次相等性检查。
检查总数=5;运行总数=5
第二次检查:乘积、求和和和比较。这需要总共6次乘法运算,总共4次加法运算,以及1次相等性检查。
检查总数=11;运行总数=16
第三次检查:乘积和比较。这需要总共4次乘法运算和1次相等性检查。
检查总数=5;运行总数=21
将两个逻辑AND运算相加,"生成多项式方法的系数"的二进制运算总数只需要:
23二进制操作
暴力检查总共需要18次相等检查、12次逻辑AND比较和5次逻辑OR比较,总共需要:
35个二进制操作
因此,严格地说,答案是肯定的,"生成多项式方法的系数"确实更有效。然而,正如@WJS所指出的,蛮力方法有更多的短路机会,因此比数学方法更有效地执行。
完全彻底
我们不能跳过检查每个三元组的所有可能组合的乘积之和。如果我们不考虑这一点,就会有无数这样的例子失败。考虑(23, 32, 45)
和(24, 30, 46)
*:
23 + 32 + 45 = 100
24 + 30 + 46 = 100
23 * 32 * 45 = 33120
24 * 30 * 46 = 33120
它们不是等价的,但给出相同的和和和乘积。然而,他们并没有给出所有可能组合的乘积的相同总和:
23 * 32 + 23 * 45 + 32 * 45 = 3211
24 * 30 + 24 * 46 + 30 * 46 = 3204
*如果人们想知道如何导出类似于上面的例子,首先生成长度为3的整数M的所有整数分区,取它们的乘积,找到重复项,然后选择一对。
如果允许排序(a1<=b1<=c1和a2<=b2<=c2(,则尝试将2^a1*3^b1*5^c1与2^a2*3^b2*5^c2进行比较(以素数2、3、5为基础(