📌  相关文章
📜  国际空间研究组织 | ISRO CS 2017 |问题 45(1)

📅  最后修改于: 2023-12-03 14:50:47.797000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2017 |问题 45

这是ISRO(国际空间研究组织)的2017年计算机科学考试中的问题45。

问题描述

给定两个整数 nk,你需要求出所有可能的由 1n 组成的数字排列,使得相邻两个数字的差的绝对值不超过 k

输入格式

输入文件包含两个整数 nk

输出格式

输出文件包含一个整数,表示满足要求的排列数量,由于答案可能很大,因此需要输出对 10^9+7 取模的结果。

样例输入
4 1
样例输出
85
解题思路

本题可以使用动态规划的方法进行求解。

定义 dp[i][j][0/1] 为有 i 个数字,最后一个数字是 j,最后两个数字的差的绝对值是否不超过 k。其中 0 表示超过,1 表示没有超过。根据这个定义,可以得到如下递推式:

dp[i][j][0] = dp[i-1][j-1][1] + dp[i-1][j-2][1] + ... + dp[i-1][j-k][1]
dp[i][j][1] = ∑dp[i-1][j'][0/1] (j - k <= j' <= j + k && j' != j)

其中第一个递推式表示当最后一个数字为 j 且最后两个数字的差的绝对值超过了 k 时,可以从所有合法的 j' 转移过来。第二个递推式表示当最后一个数字为 j 且最后两个数字的差的绝对值不超过 k 时,可以从所有合法的 j'dp[i-1][j'][0/1] 转移过来。

根据递推式,本题的动态规划算法需要使用两个循环枚举 ij,时间复杂度为 O(n^2k)。即可得到答案 dp[n][1~n][0/1] 的和。

代码实现
MOD = 10**9 + 7

n, k = map(int, input().split())

dp = [[[0, 0] for j in range(n+1)] for i in range(n+1)]
for i in range(1, n+1):
    dp[1][i][0] = i-1
    dp[1][i][1] = n-i

for i in range(2, n+1):
    for j in range(1, n+1):
        for x in range(1, k+1):
            if j-x >= 1:
                dp[i][j][0] = (dp[i][j][0] + dp[i-1][j-x][1]) % MOD
            if j+x <= n:
                dp[i][j][0] = (dp[i][j][0] + dp[i-1][j+x][1]) % MOD
        for j2 in range(1, n+1):
            if abs(j-j2) <= k and j != j2:
                dp[i][j][1] = (dp[i][j][1] + dp[i-1][j2][0] + dp[i-1][j2][1]) % MOD

ans = 0
for i in range(1, n+1):
    ans = (ans + dp[n][i][0] + dp[n][i][1]) % MOD
print(ans)

代码片段按markdown标明