📜  从0到N的数字的位差总和|套装2(1)

📅  最后修改于: 2023-12-03 15:21:54.622000             🧑  作者: Mango

从0到N的数字的位差总和|套装2

简介

本题要求计算从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