魔幻数有两种常见定义:一是快乐数,即反复计算各位数字平方和最终得1;二是自守数,即n²的末k位等于n本身。需先明确题目所指再编码,避免混淆。

什么是魔幻数?先确认定义再写代码
魔幻数(Magic Number)不是 C++ 语言标准里的概念,而是算法题或业务逻辑中自定义的判定规则。最常见的定义是:反复将一个正整数各位数字的平方和相加,最终结果为 1 的数(即“快乐数”),有些题目也称其为魔幻数;另一些场景下,魔幻数指满足 n * n % 10^k == n 的数(如 25 * 25 == 625,末两位仍是 25,称 25 是 2 位魔幻数)。不明确具体定义就写代码,大概率跑偏。
你得先确认:题目/需求里说的“魔幻数”到底指哪一种?下面分两种常见情况给实操方案。
判断快乐数型魔幻数:用快慢指针防死循环
如果魔幻数定义等价于快乐数(sum_of_squares → 1),关键难点不是计算平方和,而是识别非快乐数会陷入循环(比如 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4)。用 std::unordered_set 记录见过的数可以检测重复,但空间开销明显;更优解是快慢指针——模拟龟兔赛跑,只要两者相遇且值不为 1,就说明进环了。
- 写一个辅助函数
next_number(int n):取绝对值(防负数输入),逐位算平方和 - 初始化
slow = n,fast = next_number(n) - 循环中:更新
slow = next_number(slow),fast = next_number(next_number(fast)) - 若
slow == 1或fast == 1,返回true;若slow == fast且不为1,返回false
注意:输入可能是负数,abs(n) 必须做,否则 -123 的各位提取会出错;另外,0 不是快乐数,next_number(0) == 0,快慢指针立刻相等且不为 1,正确返回 false。
立即学习“C++免费学习笔记(深入)”;
判断自守数型魔幻数:小心整数溢出和位数匹配
如果魔幻数指自守数(automorphic number),即 n * n 的末尾几位等于 n 本身(如 76 * 76 == 5776),核心是比对低位。但直接算 n * n 很容易溢出——int 最大才约 21 亿,50000 * 50000 就超了。
- 不要无脑算
n * n,改用模运算:求n有几位,记作k,然后判断(n * n) % static_cast<long long>(pow(10, k)) == n</long> - 但
pow(10, k)返回double,可能精度丢失,应手写幂:用long long base = 1; for(int i = 0; i -
k怎么算?to_string(abs(n)).length()最稳;或者用循环除10,但注意n == 0要特判为1位 - 必须用
long long存base和乘积,否则100000级别的n就溢出
例如判断 625:它有 3 位,base = 1000,625LL * 625LL == 390625,390625 % 1000 == 625,成立。
边界和调试时最容易漏的点
魔幻数判定看似简单,实际调试时栽在细节上很常见:
-
n == 0:快乐数定义里通常只考虑正整数,但若输入含0,要明确是否合法;自守数中0满足0*0%10 == 0,但位数算出来是1,得看需求是否接受 - 输入范围没约束时,
int可能不够存中间结果,一律升到long long更安全 - 用字符串求位数时,
to_string对负数会带-,所以必须传abs(n) - 快慢指针法里,
fast初始化必须是next_number(n),不能直接设成n,否则第一次循环就相等
定义模糊、边界不处理、溢出不预防,这三处出问题的概率远高于算法逻辑本身。


















