线性dp的反向思考
[ABC281D] Max Multiple
链接:https://www.luogu.com.cn/problem/AT_abc281_d
题面翻译
给定 \(n\) 个数。现在可以从中选 \(k\) 个数,需满足他们的和为 \(d\) 的倍数。求最大和值。
translated by @liangbowen。
题目描述
非負整数列 $ A=(a_1,a_2,\ldots,a_N) $ が与えられます。
$ A $ の(添え字が相異なる) $ K $ 個の項の和として考えられる非負整数の集合を $ S $ とします。
$ S $ に含まれる $ D $ の倍数の最大値を求めてください。ただし、$ S $ に $ D $ の倍数が含まれない場合、代わりに -1
と出力してください。
输入格式
入力は以下の形式で標準入力から与えられる。
$ N $ $ K $ $ D $ $ a_1 $ $ \ldots $ $ a_N $
输出格式
答えを出力せよ。
样例 #1
样例输入 #1
4 2 2
1 2 3 4
样例输出 #1
6
样例 #2
样例输入 #2
3 1 2
1 3 5
样例输出 #2
-1
提示
制約
- $ 1\ \leq\ K\ \leq\ N\ \leq\ 100 $
- $ 1\ \leq\ D\ \leq\ 100 $
- $ 0\ \leq\ a_i\ \leq\ 10^9 $
- 入力はすべて整数
Sample Explanation 1
$ A $ から $ 2 $ 個の項を選ぶ方法を列挙すると - $ a_1 $ と $ a_2 $ を選ぶ。選ばれた項の和は $ 1+2=3 $ となる。 - $ a_1 $ と $ a_3 $ を選ぶ。選ばれた項の和は $ 1+3=4 $ となる。 - $ a_1 $ と $ a_4 $ を選ぶ。選ばれた項の和は $ 1+4=5 $ となる。 - $ a_2 $ と $ a_3 $ を選ぶ。選ばれた項の和は $ 2+3=5 $ となる。 - $ a_2 $ と $ a_4 $ を選ぶ。選ばれた項の和は $ 2+4=6 $ となる。 - $ a_3 $ と $ a_4 $ を選ぶ。選ばれた項の和は $ 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;
}