线性dp的反向思考

[ABC281D] Max Multiple

链接:https://www.luogu.com.cn/problem/AT_abc281_d

题面翻译

给定 n 个数。现在可以从中选 k 个数,需满足他们的和为 d 的倍数。求最大和值。

translated by @liangbowen

题目描述

非負整数列 A=(a1,a2,,aN) が与えられます。

A の(添え字が相異なる) K 個の項の和として考えられる非負整数の集合を S とします。

S に含まれる D の倍数の最大値を求めてください。ただし、SD の倍数が含まれない場合、代わりに -1 と出力してください。

输入格式

入力は以下の形式で標準入力から与えられる。

N K D a1 aN

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

4 2 2
1 2 3 4

样例输出 #1

6

样例 #2

样例输入 #2

3 1 2
1 3 5

样例输出 #2

-1

提示

制約

  • 1  K  N  100
  • 1  D  100
  • 0  ai  109
  • 入力はすべて整数

Sample Explanation 1

A から 2 個の項を選ぶ方法を列挙すると - a1a2 を選ぶ。選ばれた項の和は 1+2=3 となる。 - a1a3 を選ぶ。選ばれた項の和は 1+3=4 となる。 - a1a4 を選ぶ。選ばれた項の和は 1+4=5 となる。 - a2a3 を選ぶ。選ばれた項の和は 2+3=5 となる。 - a2a4 を選ぶ。選ばれた項の和は 2+4=6 となる。 - a3a4 を選ぶ。選ばれた項の和は 3+4=7 となる。 となり、S=3,4,5,6,7 となります。S に含まれる 2 の倍数のうち最大のものは 6 なので、6 と出力します。

Sample Explanation 2

この例では S=1,3,5 です。S に含まれる非負整数はいずれも 2 の倍数でないため、-1 と出力します。










解答

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 110;
LL f[N][N][N];
LL a[N];
int n, k, d;

int main()
{
	cin >> n >> k >> d;
	for (int i = 1; i <= n; i++) cin >> a[i];

	memset(f, -1, sizeof f);
	f[0][0][0] = 0;
	for (int i = 0; i <= n; i++)
		for (int j = 0; j <= k; j++)
			for (int p = 0; p < d; p++)
			{
				if (f[i][j][p] == -1) continue;    //去除不可行的情况

				LL& v = f[i + 1][j + 1][(p + a[i + 1]) % d];
				v = max(v, f[i][j][p] + a[i + 1]);

				f[i + 1][j][p] = max(f[i + 1][j][p], f[i][j][p]);
			}

	cout << f[n][k][0] << endl;
	return 0;
}
posted @   星竹z  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示