📅  最后修改于: 2023-12-03 15:21:54.622000             🧑  作者: Mango
本题要求计算从0到N的数字的位差总和。位差的定义为相邻数码的差的绝对值。
例如:当N为12345时,位差总和为1+1+1+1=4。
输入一个整数N。
输出从0到N的数字的位差总和。
5
4
本题可以使用数位DP的方法求解。将数字N转换为字符串,枚举字符串中每一位数字,分情况考虑。
例如:当枚举到字符串的第i位数字时,分别计算以该数字作为结尾,且长度为1、2、3……i的数字所能贡献的位差和。
以长度为1为例,假设当前枚举到的数字为x,则以x作为结尾,长度为1的数字只有1个,即x本身,其贡献的位差和为0。
以长度为2为例,假设当前枚举到的数字为x,则以x作为结尾,长度为2的数字有10个,分别是0x、1x、2x……9x。对于以10-99为结尾的数字,它们的贡献位差和可以由上一个数字的状态转移而来。例如:当x为3时,以3为结尾,长度为2的数字共有10个,分别是03、13、23、33、43、53、63、73、83、93。其中,03的贡献位差和为0,13的贡献位差和为1,23的贡献位差和为2,33的贡献位差和为0,将33的贡献位差和记为f[3][2][3]。当枚举到4时,以4为结尾,长度为2的数字共有10个,分别是04、14、24、34、44、54、64、74、84、94。其中,04的贡献位差和为1,14的贡献位差和为2,24的贡献位差和为3,34的贡献位差和为4,44的贡献位差和为0。对于以34-99为结尾的数字,它们的贡献位差和可以由上一个数字的状态转移而来。
以长度为3为例,假设当前枚举到的数字为x,则以x作为结尾,长度为3的数字有100个,分别是00x、01x、02x……99x。对于以100-999为结尾的数字,它们的贡献位差和可以由上一个数字的状态转移而来。以此类推,直至长度为n。
最后将各个长度的贡献位差和相加即可。
具体实现时,可以使用三维数组f[i][j][k]表示以k作为结尾,长度为j的数字所能贡献的位差和。其中,i表示字符串的长度,即数字的位数。
初始状态为f[1][1][0~9]=0。
def digit_diff_sum(n: int) -> int:
s = str(n)
m = len(s)
f = [[[0] * 10 for _ in range(m + 1)] for _ in range(m + 1)]
for i in range(10):
f[1][1][i] = 0
for i in range(2, m + 1):
for j in range(1, i + 1):
for k in range(10):
if j == 1:
f[i][j][k] = 0
else:
for l in range(10):
f[i][j][k] += abs(k - l) * f[i - 1][j - 1][l]
res = sum(f[i][j][k] for i in range(1, m + 1) for j in range(1, i + 1) for k in range(10))
return res