b_lq_倍数问题(01背包+滚动数组优化)

给了你 n 个数,希望你从这 n 个数中找到3个数,使得这三个数的和是 K 的倍数,且这个和最大。

思路
f[i][j][k] 表示从前i个数选j个数,且j个数之和模K为k的最大和,有两种决策:

  • 选第i个数:f[i][j][k]=max(f[i][j][k], f[i-1][j][k])
  • 不选第i个数:f[i][j][k]=max(f[i][j][k], f[i-1][j-1][mod]+a[i]);
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5, M=1e3+5, inf=0x7f;
int f[2][4][M], a[N], b[N];
int mod(int x, int K) {
    return (x%K+K)%K;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,K,st=1; cin>>n>>K;
    memset(f, -inf, sizeof f), f[0][0][0]=0;
    for (int i=1; i<=n; i++) cin>>a[i], b[i]=a[i]%K;
    
    for (int i=1; i<=n; i++, st^=1)
    for (int j=0; j<4; j++)
    for (int k=0; k<K; k++) {
        f[st][j][k]=max(f[st][j][k], f[st^1][j][k]);
        if (j) f[st][j][k]=max(f[st][j][k], f[st^1][j-1][mod(k-b[i], K)]+a[i]);
    }
    cout<<f[st^1][3][0];
    return 0;
}
posted @ 2020-10-06 18:01  童年の波鞋  阅读(156)  评论(0编辑  收藏  举报