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

题目大意:(文末有原题)

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

思路:

需要保证每个余数的出现次数都少于等于n/m,如果从一个余数出现次数大于n/m,则将这个余数改变为距离他最近且出现次数小于n/m的数;我们将余数可能的所有情况都压入集合,用一个数组记录出现次数,如果一个余数的出现次数大于n/m,则让这个余数出集合,这样在集合中保存的都是出现次数没有达到n/m的。

代码:

#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;       //数组c用来保存每个余数出现几次
set<int> s;

int main() {
	cin >> n >> m;
	
	for(int i = 0; i < m; i++) {	//将所有可能的余数压入集合 
		s.insert(i);
	}
	                                //s中所保存的是出现次数还没有达到n/m的余数;
	for(int i = 0; i < n; i++) {
		cin >> a[i];
		int d = a[i] % m, x; 
		
		if(d > *s.rbegin() ) {        
			x = *s.begin();	            //如果大于最大的(说明d出现次数已经够n/m次),则最近的是第一个 
		}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;
} 

原题:

题目:

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.

样例:

Input:

6 3
3 2 0 6 10 12

Output:

3
3 2 0 7 10 14 

Input:

4 2
0 1 2 3

Output:

0
0 1 2 3 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值