CoderForces999D-Equalize the Remainders(set函数的应用)


set,集合,会默认从小到大排序并去重(unordered_set 是不排序的集合,节省时间,提高效率)


set<int> s;

1. s.insert(i)    向集合中插入元素i

2. s.begin()     s的初始位置

3. s.end()        s的末位置

4. s.erase(i)     删除元素i,如果找不到则不删除

5. a.find(i)        查找元素i,若找到,则返回地址

6.a.lower_bound(i)        查找大于等于i的第一个元素,返回地址

Equalize the Remainders


You are given an array consisting of n integersa1,a2,…,an, and a positive integer m. It is guaranteed that m is a divisor of n.

In a single move, you can choose any position ii between 11 and n and increase aiai by 11.

Let's calculate cr (0≤r≤m−1) — the number of elements having remainder r when divided by mm. In other words, for each remainder, let's find the number of corresponding elements in a with that remainder.

Your task is to change the array in such a way that c0=c1=⋯=cm−1=n/m.

Find the minimum number of moves to satisfy the above requirement.


The first line of input contains two integers n and m (1≤n≤2⋅10^5,1≤m≤n). It is guaranteed that m is a divisor of n.

The second line of input contains n integers a1,a2,…,an (0≤ai≤10^9), the elements of the array.


In the first line, print a single integer — the minimum number of moves required to satisfy the following condition: for each remainder from 0 to m−1, the number of elements of the array having this remainder equals n/m;

In the second line, print any array satisfying the condition and can be obtained from the given array with the minimum number of moves. The values of the elements of the resulting array must not exceed 10^18.


给出n,m和n个数(n % m = 0),要使n个数对m的余数包含 0~m-1,并且每个余数出现的次数为n/m,对数的改变只能是a[i] += 1,问最少需要几步能够达到所需状态,并给出改变状态后的n个数




#include <iostream>
#include <set>
#include <cstdio>
#include <cstring> 
using namespace std;

typedef long long ll;
const int maxn = 2e5 + 6;
ll n, m, a[maxn], c[maxn], ans;
set<int> s;

int main() {
	cin >> n >> m;
	for(int i = 0; i < m; i++) {	//将所有可能的余数压入集合 
	for(int i = 0; i < n; i++) {
		cin >> a[i];
		int d = a[i] % m, x; 
		if(d > *s.rbegin() ) {
			x = *s.begin();	//如果 大于最大的,则最近的是第一个 
		}else {
			x = *s.lower_bound(d);		//找到大于等于d的第一个余数 

		if(++c[x] == n / m) s.erase(x);		//如果此时已经等于n/m之后,则再集合中删除x,
		ans += (x - d + m) % m;
		a[i] += (x - d + m) % m;  	
	cout << ans << endl;
	for(int i = 0; i < n; i++)  i == n - 1 ? cout << a[i] << "\n" : cout << a[i] << " ";
	return 0;









©️2019 CSDN 皮肤主题: 1024 设计师: 上身试试