1234. 倍数问题

题目链接

1234. 倍数问题

众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。

但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。

现在小葱给了你 \(n\) 个数,希望你从这 \(n\) 个数中找到三个数,使得这三个数的和是 \(K\) 的倍数,且这个和最大。

数据保证一定有解。

输入格式

第一行包括 \(2\) 个正整数 \(n, K\)

第二行 \(n\) 个正整数,代表给定的 \(n\) 个数。

输出格式

输出一行一个整数代表所求的和。

数据范围

\(1≤n≤10^5,\)
\(1≤K≤10^3,\)
给定的 \(n\) 个数均不超过 \(10^8\)

输入样例:

4 3
1 2 3 4

输出样例:

9

解题思路

dp,贪心

贪心策略:由于需要找出 \(3\) 个和模 \(k\)\(0\) 的最大数,所以不妨将所有模 \(k\) 的余数的所有数提取出来,只需要前 \(3\) 就行
这样本质上就是一个背包问题了:

  • 状态表示:\(f[i][j][t]\) 表示前 \(i\) 个数,选了 \(t\) 个数,和模 \(k\) 结果为 \(j\) 的最大和

  • 状态计算:\(f[i][j][t]=max(f[i-1][j][t],f[i-1][(j-a[i]\%k+k)\%k][t-1])\)

这里需要优化空间,滚动掉第一维,但需要逆序循环 \(t\),这样是为了防止 \(i\) 层更新后的值影响到本身

  • 时间复杂度:\(O(9000\times k)\)

代码

// Problem: 倍数问题
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1236/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

int n,k,f[1005][4];
int main()
{
    cin>>n>>k;
    vector<int> a[k];
    for(int i=1;i<=n;i++)
    {
    	int x;
    	cin>>x;
    	a[x%k].pb(x);
    }
    memset(f,-0x3f,sizeof f);
    f[0][0]=0;
   	for(int i=0;i<k;i++)
   	{
   		sort(a[i].begin(),a[i].end(),greater<>());
   		for(int j=0;j<3&&j<a[i].size();j++)
   		{
   			int x=a[i][j];
   			for(int t=0;t<k;t++)
   			    for(int u=3;u>=1;u--)f[t][u]=max(f[t][u],f[(t-x%k+k)%k][u-1]+x);
   		}
   	}
    cout<<f[0][3];
    return 0;
}
posted @ 2022-02-20 16:19  zyy2001  阅读(54)  评论(0编辑  收藏  举报