Equalize the Remainders CodeForces - 999D(set相关函数使用)

题意:给你一个大小为n的数组,m是n的一个divisor。每次可以对ai+1,问最少的次数让数组中的每个元素除m 的余数 从0到m-1 各有n/m个。

题解:贪心思想如果余数要加,那么能加最少就加最少,我找出要加到最少的目标余数进而就可以的出这一次的操作次数,然后该元素也会做出相应改变。具体看代码。

重点用到了三个我不会的set函数:set.rbegin()返回set中最大的元素,set.begin()返回最小元素,set.lowerbound(int x)二分返回大于等于x的第一个元素。

AC代码:

#include <iostream>
#include <set>
using namespace std;
const int maxn=2e5+6;
typedef long long ll;
ll n,m,a[maxn],num[maxn],ans;
set<int>s;
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=0;i<m;i++)s.insert(i);//先把所有余数都压进去
	for(int i=0;i<n;i++){
		cin>>a[i];
		int d=a[i]%m,x;//x代表我要加到目标余数 
		//贪心思想,寻找d所能加到的最近的余数 
		if(d>*s.rbegin())x=*s.begin();//d比最大的余数还大 ,贪心,一直加到最小的余数就行
		else x=*s.lower_bound(d);//d就在余数范围内,找到大于等于d的第一个余数 
		if(++num[x]==n/m)s.erase(x);//凑够了,删去对应的余数 
		ans+=(x-d+m)%m;
		a[i]+=(x-d+m)%m;//元素发生相应改变 
	}
	cout<<ans<<endl; 
	for(int i=0;i<n;i++)cout<<a[i]<<" ";
} 
原创文章 38 获赞 7 访问量 1734

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/106144625
今日推荐