📅  最后修改于: 2023-12-03 15:18:04.632000             🧑  作者: Mango
在编程时,我们经常需要计算一些数的个数,特别是在数论、组合数学、概率等领域。本文将介绍一道与计数相关的题目,即N位数的计数,相邻位数的绝对差不超过K。
给定正整数N和K,求由N位数字组成的正整数中,每相邻两位数字的绝对差不超过K的数字个数。例如当N=3,K=2时,满足条件的数字为101, 111, 121, 131, 141, 212, 232, 252, 313, 333, 343, 353, 363, 373, 383, 393, 454, 474, 494, 505, 525, 535, 545, 555, 565, 575, 585, 595, 656, 676, 696, 707, 727, 737, 747, 757, 767, 777, 787, 797, 858, 878, 898, 909, 929, 939, 949, 959, 969, 979, 989, 共48个。
若N=1,则符合条件的数字个数为K+1;若N>1,则可以使用动态规划的思想求解,设dp[i][j]表示i位数字中,个位数字为j时,满足条件的数字个数。则当i>1时,dp[i][j]的值可以通过dp[i-1][k]转移得到,具体转移方式如下:
for k in range(max(0, j-K), min(10, j+K+1)):
dp[i][j] += dp[i-1][k]
其中,max(0, j-K)和min(10, j+K+1)保证了计算时不会出现负数和大于等于10的数字。
最终答案为所有dp[N][j]之和。
def count_numbers(n: int, k: int) -> int:
dp = [[0] * 10 for _ in range(n+1)]
for i in range(10):
dp[1][i] = 1
for i in range(2, n+1):
for j in range(10):
for k in range(max(0, j-k), min(10, j+k+1)):
dp[i][j] += dp[i-1][k]
ans = sum(dp[n])
return ans
本题利用动态规划的思想,优雅地解决了计数问题。同时也延伸了动态规划的应用领域,以及思考动态规划方程的技巧和方法。