我想找到方程a^3 + b^3 = c^3 + d^3
的所有正整数解,其中a, b, c, d
是1 to 1000
强力解决方案继续计算每个(a,b)对的所有(c,d)对。 我想改进这个算法。我想创建一次(c,d)对的列表。然后,当我们有(a,b)对时,找到(c,d)列表中的匹配。我们可以通过将每个(c,d)对插入到哈希表中来快速定位匹配,哈希表从总和映射到对(或者更确切地说是具有该总和的对的列表)
n= 1000
for c from 1 to n
for d from 1 to n
result = c^3 + d^3
append (c,d) to list at value map[result]
for a from 1 to n
for b from 1 to n
result = a^3 + b^3
list = map.get(result)
foreach pair in list
print a,b, pair
我说我们有O(n ^ 2)解决方案吗?为什么?我们怎样才能改善它?什么是c#实现?
此外,也许一旦我们拥有所有(c,d)对的地图,我们就可以直接使用它。我们不需要生成(a,b)对。每个(a,b)都已经在地图中。如何实现这个想法?
答案 0 :(得分:6)
您可以分组所有可能的总和,并打印出包含多个项的组。这是O(N**2)
算法:
// key is sum and value is a list of representations
Dictionary<int, List<Tuple<int, int>>> solutions =
new Dictionary<int, List<Tuple<int, int>>>();
for (int a = 1; a <= 1000; ++a)
for (int b = a; b <= 1000; ++b) {
int sum = a * a * a + b * b * b;
List<Tuple<int, int>> list = null;
if (!solutions.TryGetValue(sum, out list)) {
list = new List<Tuple<int, int>>();
solutions.Add(sum, list);
}
list.Add(new Tuple<int, int>(a, b));
}
String report = String.Join(Environment.NewLine,
solutions.Values
.Where(list => list.Count > 1) // more than one item
.Select(list => String.Join(", ",
list.Select(item => String.Format("({0}, {1})", item.Item1, item.Item2)))));
Console.Write(report);
输出( 1585 行)
(1, 12), (9, 10)
(1, 103), (64, 94)
(1, 150), (73, 144)
(1, 249), (135, 235)
(1, 495), (334, 438)
...
(11, 493), (90, 492), (346, 428) // <- notice three representations of the same sum
...
(663, 858), (719, 820)
(669, 978), (821, 880)
(692, 942), (720, 926)
(718, 920), (816, 846)
(792, 901), (829, 870)
所以我们有
1**3 + 12**3 == 9**3 + 10**3
...
11**3 + 493**3 == 90**3 + 492**3 == 346**3 + 428**3
...
792**3 + 901**3 == 829**3 + 870**3
我们有 8 三重表示可能会很有趣:
(11, 493), (90, 492), (346, 428)
(15, 930), (198, 927), (295, 920)
(22, 986), (180, 984), (692, 856)
(70, 560), (198, 552), (315, 525)
(111, 522), (359, 460), (408, 423)
(167, 436), (228, 423), (255, 414)
(300, 670), (339, 661), (510, 580)
(334, 872), (456, 846), (510, 828)
答案 1 :(得分:2)
在纯LINQ中重申@Dmitry的答案(谁应该得到所有的功劳):
from a in Enumerable.Range(1, 1000)
from b in Enumerable.Range(a, 1000 - a + 1)
let sum = a * a * a + b * b * b
group $"{a}^3 + {b}^3" by sum into g
where g.Count() > 1
orderby g.Key // just for niceness
select $"{g.Key} = " + String.Join(" = ", g)
答案 2 :(得分:0)
我们甚至可以实现一个更简单的解决方案,为&#34; a&#34;和&#34; b&#34;,然后将这些添加到Dictionary<int, List<Tuple<int,int>>>
作为@Dimitry状态,但是,然后将报告生成更改为:
foreach (List<Tuple<int,int>> l in solutions.Values) {
foreach(Tuple<int,int> t1 in l) {
foreach(Tuple<int,int> t2 in l) {
Console.Write("({0},{1})({2},{3})", t1.Item1, t1.Item2, t2.Item1, t2.Item2);
}
}
}
无需检查其中一个解决方案是否包含列表中的多个元组。单个元组列表也是有效的解决方案,因为任何(a,b)值也可以由(c,d)表示,使 c = a 和 d = b ,因此这些也应包含在报告中。
通过这种方式,您还可以解决@Dimitry注意到的具有三重表示的解决方案的不一致性。
答案 3 :(得分:0)
@Dmitry的答案是一个很好的第一步,但缺少一些方案。 @pau提到了一种情况,其中a == b-即使在迭代过程中只对它们进行一次计数也应将其包括在内。
此外,第二个循环需要将变量b
重置为1
,而不是a
。否则,您将不会捕获(1,2)=(2,1)的组合。
更新:您可以保持第二个循环不变,只需确保自动包含(a,b)的倒数即可。因此,从本质上讲,每个(a,b)对都应该自动包括在内,因为它的对等(b,a)对等。