5.3信心杯T1 Divisibility

题解(by 石二lyh orz)

   一组数两两之差可以整除m,当且仅当它们在模m的剩余系意义下相等。对于每个数a[i],将其加入a[i]%m的代表集合中,判断0~m-1是否有一个集合的个数大于等于k即可。输出字典序最小的方案时,只需要比较所有满足题意的集合中的最小值,最小值最小的集合即为答案,排序输出前k个即可。

   时间复杂度o(n+klogk)

代码

//by ziwan
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm> 
const int MAX_N=1e6;
using namespace std;
struct nums{
	int a,p;//a为数值 p为%m意义下的剩余系 
}num[MAX_N];
bool cmp(nums x,nums y){
	return x.a<y.a;
};
int n,m,k,cnt[MAX_N],bl,bol[MAX_N],ans;
int main()
{
	cin>>n>>k>>m;//给定n个数 选出恰好k个数 两两之差可以被m整除
	for(int i=1;i<=n;i++)
	{
		cin>>num[i].a;
		num[i].p=num[i].a%m;
		cnt[num[i].p]++;//给剩余系下存的num计数 
	}
	sort(num+1,num+n+1,cmp);
	for(int i=0;i<m;i++)
		if(cnt[i]>=k) 
	{
		bl=1;
		bol[i]=1;
	}		
	if(bl==0) cout<<"No"<<endl; 
	else
	{
		cout<<"Yes"<<endl;
		for(int i=1;i<=n;i++)
    	{
	    	if(bol[num[i].p]) {
			ans=num[i].p;
			break;}
	    }
	int tot=0;	
		for(int i=1;i<=n;i++)
		{
			if(num[i].p==ans)
			{
				cout<<num[i].a<<" ";
				if(++tot==k) break;
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值