题目:
给你一个正整数 n
,请你返回 n
的 惩罚数 。n
的 惩罚数 定义为所有满足以下条件 i
的数的平方和:
1 <= i <= n
i * i
的十进制表示的字符串可以分割成若干连续子字符串,且这些子字符串对应的整数值之和等于i
。
示例 1:
输入:n = 10 输出:182 解释:总共有 3 个整数 i 满足要求: - 1 ,因为 1 * 1 = 1 - 9 ,因为 9 * 9 = 81 ,且 81 可以分割成 8 + 1 。 - 10 ,因为 10 * 10 = 100 ,且 100 可以分割成 10 + 0 。 因此,10 的惩罚数为 1 + 81 + 100 = 182
示例 2:
输入:n = 37 输出:1478 解释:总共有 4 个整数 i 满足要求: - 1 ,因为 1 * 1 = 1 - 9 ,因为 9 * 9 = 81 ,且 81 可以分割成 8 + 1 。 - 10 ,因为 10 * 10 = 100 ,且 100 可以分割成 10 + 0 。 - 36 ,因为 36 * 36 = 1296 ,且 1296 可以分割成 1 + 29 + 6 。 因此,37 的惩罚数为 1 + 81 + 100 + 1296 = 1478
提示:
1 <= n <= 1000
思路:
寻找一个给定数字 n 以下,满足惩罚数条件的所有数字,并将这些数字求和。
所谓的惩罚数,是指一个正整数 x,其各位数字的 n 次方之和等于 x 本身。本题的解题思路是先
- 定义一个辅助函数 check(s, i, x),用于检查从字符串 s 的第 i 个字符开始,各位数字的 n 次方之和是否等于 x。其中,s 是待检查的字符串,i 是当前检查的起始位置,x 是要检查的目标值。
- 在 check 函数中,首先判断当前检查的位置是否超过了字符串的长度,如果超过了,说明所有数字都已经检查过了,此时判断 x 是否为 0,如果是,则说明找到了一个惩罚数,返回 True,否则返回 False。
- 如果当前检查的位置没有超过字符串的长度,将字符串从当前位置开始,按位取出数字,并计算其 n 次方,如果该数字大于 x,则跳出内层循环。
- 然后递归调用 check 函数,从下一个位置开始检查,直到所有位置都检查完或者找到一个满足条件的惩罚数。
- 在主函数中,初始化 ans 为 0,然后从 1 到 n 遍历每个数字 i,计算 i 的平方,并将其转换为字符串,然后调用 check 函数检查该数字是否满足惩罚数条件。
- 如果满足条件,就将该数字加到 ans 中。
- 遍历完成后,返回 ans。
- 本代码的解题思路是利用递归和数学公式,在给定数字范围内寻找满足惩罚数条件的所有数字,并将它们求和。
代码:
class Solution:
def punishmentNumber(self, n: int) -> int:
def check(s:str, i:int, x:int)->bool:
m=len(s)
if i>=m:
return x==0
y=0
for j in range(i,m):
y=y*10 + int(s[j])
if y>x:
break
if check(s,j+1,x-y):
return True
return False
ans=0
for i in range(1,n+1):
x=i*i
if check(str(x),0,i):
ans+=x
return ans