1、正向思路:动态规划
令dp[i]表示:所取之和sum最大,且sum % k = i。
具体代码如下。注意每次状态转移之前,要备份一下dp数组。
#include <climits> #include <iostream> #include <vector> using namespace std; int main() { int n, k; long long a; cin >> n >> k; vector<long long> dp(k, LLONG_MIN); dp[0] = 0; while(n--) { cin >> a; vector<long long> tmp(k); for(int i = 0; i < k; ++i) { int j = (a + i) % k; tmp[j] = max(dp[j], dp[i] + a); } swap(dp, tmp); } cout << (dp[0] == 0 ? -1 : dp[0]); }
2、反向思路:动态规划
换个思路,将数组的所有数字相加得到sum,计算mod = sum % k的值。
若mod == 0,那么直接输出sum。
否则本题可以转化为:从数组a中挑出若干个数,使其之和对k取余为mod,求这个和的最小值。
下面贴出代码。
#include <iostream> #include <vector> using namespace std; int main() { int n, k; cin >> n >> k; vector<long long> a(n); long long sum = 0; for (auto& i : a) { cin >> i; sum += i; } int mod = sum % k; if(mod == 0) { cout << sum; return 0; } vector<long long> dp(k, 1e13); dp[0] = 0; for(auto& i : a) { vector<long long> tmp(k); for(int j = 0; j < k; ++j) { int p = (i + j) % k; tmp[p] = min(dp[p], dp[j] + i); } swap(tmp, dp); } if(dp[mod] == 1e13 || dp[mod] == sum) { cout << -1; } else { cout << sum - dp[mod]; } }