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

SET

set,集合,会默认从小到大排序并去重(unordered_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个数

思路:

保证每个余数的出现次数都少于等于m/n,如果从一个数开始大于n/m,则将这个数改变为距离他最近且余数小于m/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++) {	//将所有可能的余数压入集合 
		s.insert(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,
								//即保证了余数为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 设计师: 上身试试
应支付0元
点击重新获取
扫码支付

支付成功即可阅读