卡普列加数是指正整数n满足其平方n²可拆分为左右两段,右段非零且长度不超过n的位数,且左右段之和等于n;判断逻辑为枚举右段长度k∈[1,len(n)],计算right=n²%10ᵏ、left=n²/10ᵏ,检查right≠0且left+right==n。

什么是卡普列加数,判断逻辑怎么写
一个正整数 n 是卡普列加数,当且仅当它的平方 n * n 拆成两部分(左段 + 右段)后,两部分之和恰好等于 n,且右段必须非零、长度不超过原数位数。比如 9:平方是 81,拆成 8 和 1,8 + 1 == 9,成立。
关键不是“能不能拆”,而是“是否存在一种合法拆法”。拆分位置只能在末尾若干位——右段长度从 1 到 len(n)(即 n 的十进制位数),但右段不能全为 0(即 right == 0 排除),左段允许为 0(如 n == 1,1*1 == 1,拆成 "" 和 "1",左段视为 0)。
用 to_string 和字符串切片实现最直观
把 n*n 转成字符串,枚举所有合法的分割点:
- 先算
sq = n * n,转成string s = to_string(sq) - 设
d = to_string(n).length(),右段最多取d位,所以分割点i从max(1, (int)s.length() - d)开始,到s.length() - 1结束(保证右段至少 1 位、左段可为空) - 对每个
i,左段是s.substr(0, i)(可能为空),右段是s.substr(i);把它们转成整数left和right;若right != 0 && left + right == n,就返回true
示例:n = 45,sq = 2025,d = 2,s = "2025",尝试 i = 2(右段取后 2 位)→ "20" + "25" → 20 + 25 == 45,命中。
立即学习“C++免费学习笔记(深入)”;
避免字符串转换的纯数值解法
用除法和取模模拟“取右段 k 位”更高效,尤其对大数(但注意 long long 上限):
- 预计算
base = 10,循环k次(k从 1 到d),每次base *= 10 - 对每个
k,right = sq % base,left = sq / base - 要求
right != 0(排除右段为 0),且left + right == n - 注意:当
sq 时,<code>left为 0,这是合法的(如n=1)
陷阱:base 可能溢出,所以 k 循环上限应设为 min(d, number_of_digits(sq)),或直接用字符串长度更稳妥。
边界情况和易错点
1 是卡普列加数(1*1 == 1,右段 1,左段空 → 0,0 + 1 == 1),但很多人漏掉;10 不是(100 拆成 10+0 不合法,1+00 → 1+0 也不合法,因右段为 0)。
- 右段为 0 必须跳过(如
n=100,10000拆成100+00→right==0,无效) -
n=297是经典例子(88209→88 + 209 == 297),右段长度 3,正好等于n的位数 - 不要只试一种拆法——必须遍历所有可能的右段长度
真正容易被忽略的是:右段长度上限不是任意的,它严格受限于原数位数,否则会出现 999 → 998001,若容许右段取 4 位(8001),左段 99,99 + 8001 == 8100 ≠ 999,但这不是卡普列加定义允许的拆法。


















