试题 历届试题 倍数问题(思维、数学)
题解:题目是要求找到三个数之和最大并取模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 */