为正整数集定义了以下迭代序列:
n→n / 2(n是偶数)
n→3n + 1(n为奇数)
使用上面的规则并从13开始,我们生成以下序列:
13→40→20→10→5→16→8→4→2→1
可以看出,该序列(从13开始,在1结束)包含 10个学期。虽然尚未证实(Collatz问题),但据认为所有起始数字都以1结束。
哪个起始编号低于一百万,产生最长的链?
这是我对手头问题的解决方案。
static void Main(string[] args)
{
int possCounter = 0;
int largestChain = 0;
int largestChainNum = 0;
int chainNum = 0;
for (int i = 2; i <= 999999; i++)
{
chainNum = i;
possCounter = 1;
while (chainNum != 1)
{
if (chainNum % 2 == 0)
{
chainNum = chainNum / 2;
}
else
{
chainNum = (3 * chainNum) + 1;
}
possCounter++;
Console.WriteLine(chainNum);
}
if (possCounter > largestChain)
{
largestChainNum = i;
largestChain = possCounter;
}
}
Console.WriteLine(largestChainNum);
Console.ReadLine();
}
我在Console.WriteLine(chainNum)
之后放置possCounter++
只是为了检查我的代码是否正常运行。它会正常运行,然而,在某一点它开始运行负数。我不知道我的代码出了什么问题。
答案 0 :(得分:1)
这是一个整数溢出。如果你使用更大的类型(如Long),它应该可以正常工作。
答案 1 :(得分:1)
解决问题(跟踪序列)时,您将遇到数字
56991483520
大于int.MaxValue
,因此你会有溢出;我建议将long
用于序列成员。一个优化提示更多是通过序列项的系列更新:已跟踪
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
您知道40
,20
和16
的长度,并且无需再次计算这些数字
private static Dictionary<long, int> s_Counts = new Dictionary<long, int>() {
{1, 1},
};
private static void AppendCounts(long n) {
List<long> list = new List<long>();
for (; !s_Counts.ContainsKey(n); n = n % 2 == 0 ? n / 2 : 3 * n + 1)
list.Add(n);
int count = s_Counts[n];
for (int i = list.Count - 1; i >= 0; --i)
s_Counts.Add(list[i], count + list.Count - i);
}
...
for (int i = 1; i < 1000000; ++i)
AppendCounts(i);
KeyValuePair<long, int> max = new KeyValuePair<long, int>(0, 0);
foreach (var pair in s_Counts)
if (pair.Value > max.Value)
max = pair;
Console("{0} generates {1} values", max.Key, max.Value);
结果是
837799 generates 525 values