A-糖果
由于在维护世界和平的事务中做出巨大贡献,蒜头君被赠予糖果公司若干无限量糖果免费优惠券。蒜头君可以从糖果公司的 N 件产品中任意选择若干件带回家享用。糖果公司的 N 件产品每件都包含数量不同的糖果。蒜头君希望他选择的产品包含的糖果总数是K的整数倍,这样他才能平均地将糖果分给帮助他维护世界和平的伙伴们。当然,在满足这一条件的基础上,糖果总数越多越好。蒜头君最多能带走多少糖果呢?
注意:蒜头君只能将糖果公司的产品整件带走
输入格式
第一行包含两个整数 N(1 < N < 100)和区(1 < K< 100);以下 N 行每行 1 个整数,表示糖果公司该件产品中包含的糖果数目,不超过 1000000。
输出格式
符合要求的最多能达到的糖果总数,如果不能达到 区 的倍数这一要求,输出 0。
样例解释
蒜头君的选择是2+3+4+5 =14,这样糖果总数是7的倍数,并且是总数最多的选择。
Sample 1
Inputcopy | Outputcopy |
---|---|
5 7 1 2 3 4 5 | 14 |
解题思路:
dp[i][j]
表示在考虑前i
个产品时,吃掉的糖果总数模k
余j
的最大糖果数。
动态规划的思路如下:
-
初始化:
dp[0][:]
的所有元素都设置为0,因为没有产品可以选择时,吃掉的糖果总数自然是0。 -
状态转移:对于每个产品
i
(从1到n
),我们有两种选择:吃这个产品或者不吃。-
如果选择吃第
i
个产品,那么当前吃掉的糖果总数模k
的余数将会变化。如果之前吃掉的糖果总数模k
余j
,加上第i
个产品的糖果数后,余数将是(dp[i-1][j] + candies[i-1]) % k
。我们需要更新dp[i][remainder]
,其中remainder
是新的余数,以确保它包含吃掉第i
个产品后可能得到的最大糖果数。 -
如果选择不吃第
i
个产品,那么当前状态应该和上一个产品时的状态一样,即dp[i][:] = dp[i-1][:]
。
因此,状态转移方程是:
dp[i][remainder] = max(dp[i][remainder], dp[i-1][j] + candies[i-1])
其中
remainder = (dp[i-1][j] + candies[i-1]) % k
。 -
python:
def max_candies(n, k, candies):
# 初始化动态规划数组
dp = [[0] * k for _ in range(n + 1)]
# 遍历每件产品
for i in range(1, n + 1):
# 复制上一个状态
dp[i][:] = dp[i - 1][:]
# 更新状态
for j in range(k):
remainder = (dp[i - 1][j] + candies[i - 1]) % k
dp[i][remainder] = max(dp[i][remainder], dp[i - 1][j] + candies[i - 1])
# 返回最终的最大糖果总数
return dp[n][0]
# 读取输入
n, k = map(int, input().split())
candies=[]
for i in range(n):
candies.append(int(input()))
# 计算并输出结果
result = max_candies(n, k, candies)
print(result)