生成模10的Pisano Period时多2个值的问题排查
嘿,我来帮你排查一下为什么你的Pisano序列会多出2个元素!
问题根源分析
你遇到的62个元素的问题,核心在于Pisano周期的终止条件判断时机:
- Pisano周期的定义是:从
0,1开始,当序列再次出现0,1时,一个完整的周期就结束了。 - 你的代码初始已经把
0,1加入了pisanoSequence,然后在递归中每次先添加新元素,再检查最后两位是否为1,0(也就是序列末尾是0,1)。这会导致你把下一个周期的开头0,1也加入了序列,所以原本60个元素的周期,加上额外的0,1,总长度就变成了62。
举个例子:模10的Pisano周期是60,对应序列是F₀到F₅₉ mod10,而F₆₀ mod10=0,F₆₁ mod10=1——这两个就是你多出来的元素。
代码修正方案
我会给你调整代码,解决这个问题,同时优化实现逻辑(比如用循环代替递归,避免栈溢出风险,去掉不必要的全局变量):
#include <iostream> #include <vector> using namespace std; vector<uint64_t> generatePisanoSequence(int mod) { vector<uint64_t> sequence; uint64_t a = 0, b = 1; sequence.push_back(a); if (mod == 1) { // 特殊情况:模1时所有数都是0,周期为1 return sequence; } sequence.push_back(b); while (true) { uint64_t c = (a + b) % mod; a = b; b = c; // 当再次出现0,1时,说明周期结束,停止添加 if (a == 0 && b == 1) { break; } sequence.push_back(a); } return sequence; } int main() { const int mod = 10; vector<uint64_t> pisanoSequence = generatePisanoSequence(mod); int period = pisanoSequence.size(); // 现在period是60,符合预期 uint64_t n; cin >> n; // 计算前n项和:S(n) = F(n+2) - 1,取模10 // 先求(n+2)对应的Pisano序列索引 int idx = (n + 2) % period; uint64_t fn_plus_2_mod = pisanoSequence[idx]; uint64_t sum_mod = (fn_plus_2_mod - 1 + mod) % mod; // +mod避免负数 cout << sum_mod << endl; return 0; }
关键修改点说明
- 循环替代递归:递归虽然能工作,但对于更大的模(比如模1000),递归深度会很高,容易触发栈溢出。循环实现更稳定高效。
- 正确的周期终止判断:在生成新元素前,检查是否回到
0,1,这样不会把下一个周期的开头加入序列,生成的序列正好是一个完整周期的元素(60个)。 - 移除全局变量:全局变量容易引发意外问题,改成函数内局部变量并返回序列,代码更整洁。
- 鲁棒的取模处理:计算
(fn_plus_2_mod -1)时,加上mod再取模,避免出现负数(比如当fn_plus_2_mod=0时,0-1=-1,加10后取模得到9,符合预期)。
验证结果
当你运行修正后的代码,生成的pisanoSequence长度会是60,完全符合模10的Pisano周期。输入任意n,都能正确计算前n项斐波那契数的最后一位。
内容的提问来源于stack exchange,提问作者Daria
相关产品推荐
相关产品推荐

