题目描述
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。
输入
从标准输入读入数据。
第一行包括 2 个正整数 n, K。
第二行 n 个正整数,代表给定的 n 个数。
输出
输出到标准输出。
输出一行一个整数代表所求的和。
样例输入
4 3
1 2 3 4
样例输出
9
提示
对于 30% 的数据,n <= 100。
对于 60% 的数据,n <= 1000。
对于另外 20% 的数据,K <= 10。
对于 100% 的数据,1 <= n <= 10^5, 1 <= K <= 10^3,给定的 n 个数均不超过 10^8。
思路:因为k只有1e3的数据量,因此我们可以从k入手。我们先按照每个数对k取余的数字将每个数字分类。然后两重循环枚举0~k-1,这样就可以求第三个数字。然后不对的更新最大值就可以了。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e5+100;
const int maxm=1e3+100;
int a[maxx];
vector<int> p[maxm];
int n,k;
bool cmp(int a,int b){return a>b;}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
p[a[i]%k].push_back(a[i]);
}
for(int i=0;i<k;i++) sort(p[i].begin(),p[i].end(),cmp);
int _max=0;
for(int i=0;i<k;i++)
{
if(p[i].size()==0) continue;
if((3*i==k||i==0)&&p[i].size()>=3) _max=max(_max,p[i][0]+p[i][1]+p[i][2]);
for(int j=0;j<k;j++)
{
if(!p[j].size()) continue;
int z=k-(i+j)%k;//!!这里要注意。
if(z<0) continue;
if(z==i&&z==j) continue;
else if((i!=j)&&(z==i||z==j)&&p[z].size()>=2) _max=max(_max,p[i][0]+p[j][0]+p[z][1]);
else if(i==j&&p[i].size()>=2&&p[z].size()>=1) _max=max(_max,p[i][0]+p[j][1]+p[z][0]);
else if(i!=j&&i!=z&&j!=z&&p[i].size()>=1&&p[j].size()>=1&&p[z].size()>=1) _max=max(_max,p[i][0]+p[j][0]+p[z][0]);
}
}
printf("%d\n",_max);
return 0;
}
努力加油a啊,(o)/~