如何找到三次方程的所有正整数解?

时间:2016-06-16 15:11:09

标签: c# algorithm

我想找到方程a^3 + b^3 = c^3 + d^3的所有正整数解,其中a, b, c, d1 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)都已经在地图中。如何实现这个想法?

4 个答案:

答案 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)对等。