📌  相关文章
📜  可以被给定的N位数字集(最多由0和7组成)的最大数,可以被50整除(1)

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

做法:背包问题

问题描述

给定一个最多由0和7组成的N位数字集,求该集合中能够构成的最大可以被50整除的数。

解题思路

为了方便讲解,当成人数、重量每一个物品都是1处理(正常是与该物品转换后的数值相同),考虑一下0/7两个数字在构成能否被50整除具有互补性,以及N较大的时间复杂度,容易想到使用动态规划求解。

定义状态 $f(i,j)$ 表示用前 $i$ 个数字,且模 50 余数为 $j$ 时的最大位数。

对于每一个状态 $f(i,j)$ ,存在以下两种转移情况:

  • 当前不选该位数字,则 $f(i,j)=f(i-1,j)$
  • 当前选它则 $f(i,j)=\max(f(i,j),f(i-1,(10\times j+d_i)\mod 50))$,其中 $d_i$ 是第 $i$ 个数字。

最后从大到小枚举位数,直接输出最终的方案即可得到答案。

代码实现
def solution(n: str) -> str:
    n = [int(x) for x in n]
    f = [[-int(1e9)] * 50 for _ in range(len(n) + 1)]
    f[0][0] = 0
    for i in range(1, len(n) + 1):
        for j in range(50):
            f[i][j] = max(f[i][j], f[i - 1][j])
            f[i][(10 * j + n[i - 1]) % 50] = max(f[i][(10 * j + n[i - 1]) % 50], f[i - 1][j] + 1)
    if f[len(n)][0] <= 0:
        return 'no solution'
    ans = []
    j = 0
    for i in range(len(n), 0, -1):
        if j == 0 and f[i][j] > f[i - 1][j]:
            ans.append(str(n[i - 1]))
            j = (j - n[i - 1] * pow(10, f[i - 1][j] - 1, 50)) % 50
    return ''.join(ans[::-1])
时间复杂度

状态数 $O(n\times50)$,转移时间为 $O(1)$,因此总复杂度 $O(n^2)$。

参考资料

洛谷P5266 [Ynoi2018]Cycle