试题 历届试题 倍数问题(思维、数学)

传送门

 

题解:题目是要求找到三个数之和最大并取模K等于0。

我们可以将每个数对k取模,并记录取余k相同的数中最大三个数(vector模拟即可)

那么我们只需要枚举这其中所有的三个余数之和结果取余k为0的方案(要防止取余结果为负),取最大和即可。

每个数只能取一个,所以需要开几个num数组记录当前余数中最大数的下标,注意每次枚举完要恢复原先的存储。

算法复杂度(k^2=1e6)

#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
const int M = 100005;
vector<int>v[N];
int num1[M],num2[M];
void init(int x,int y,int z){
    num1[x]=num2[x];
    num1[y]=num2[y];
    num1[z]=num2[z];
}
int main(){
    int n,k,a;scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%d",&a);
        if(v[a%k].size()<3){v[a%k].push_back(a);}
        else if(a>v[a%k][0]){v[a%k][0]=a;}
        sort(v[a%k].begin(),v[a%k].end());
    }
    for(int i=0;i<k;i++){
        num1[i]=num2[i]=v[i].size();
    }
    long long maxx=-1;
    for(int i=0;i<k;i++){
        long long ans;
        for(int j=0;j<k;j++){
            ans=0;
            int z=(k-i-j+k)%k; 
            if(num1[i]<1){init(i,j,z);continue;}
            ans+=v[i][--num1[i]];
            if(num1[j]<1){init(i,j,z);continue;}
            ans+=v[j][--num1[j]];
            if(num1[z]<1){init(i,j,z);continue;}
            ans+=v[z][--num1[z]];
            init(i,j,z);
            maxx=max(maxx,ans);
        }
    }
    cout<<maxx<<endl;
    return 0;
} 
/*
10 8
17 9 19 43 32 40 34 100 89 20
232
*/

 

posted @ 2020-11-09 14:41  mohari  阅读(217)  评论(0编辑  收藏  举报