题 意:输入n个数,让你从中选出k个数,要求这k个数,任意两个数的差模m均是整数。
数据范围:
2<=k<=n<=1e5
1<=m<=1e5
输入样例:
3 2 3
1 8 4
输出样例:
Yes
1 4
思路:这个的关键点就是同余定理,简单的介绍同余定理,若(a-b)%m 是一个整数,则称a与b对模m同余。记做 a≡b(mod m) 。或者a%m == b%m 。 也就是说如果 如果a%m == b%m 那么 (a-b)%m也会是一个整数。那么这题就好写了,那也就是说,ai%m的余数相同的那些数,两个只差也一定可以整出m。接下来就只需要记录一下出现次数最多的余数times,然后判断times是否大于k,小于则No,大于则从余数等于出现次数最多的那个余数中选出k的数出来则可。
收获:明白什么是同余,以及同余简单的应用。若(a-b)%m = 0 则a%m == b%m
//debug的顺序
//先检查细节
//算法正确性
//算法细节 大部分错误 都会出在算法细节上面的
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+5;
typedef long long ll;
int a[maxn];
vector<int> vec;
int c[maxn];
int n,k,m;
int main(){
scanf("%d%d%d",&n,&k,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
c[a[i]%m]++;
}
int MAX = -INF;
int value;
for(int i=0;i<m;i++){
if(c[i] > MAX) {
MAX = c[i];
value = i;
}
}
if(MAX < k){
printf("No\n");
return 0;
}
printf("Yes\n");
for(int i=0;i<n;i++){
if(a[i]%m == value){
vec.push_back(a[i]);
}
if(vec.size()>=k) break;
}
for(int i=0;i<vec.size();i++){
printf("%d%c",vec[i],i== vec.size()-1?'\n':' ');
}
return 0;
}