Codeforces Round #702 (Div. 3)——B. Balanced Remainders

B. Balanced Remainders

题意

T组测试样例,每组n个数据,问最少需要经过多少次操作【操作这样规定,每一次可以在数组的其中一个数上加一】可以使得当前这组数据模3之后余0、余1、余2的个数相等,即为数组个数的三分之一。

测试样例解释

  • input
    1
    6
    0 2 5 5 4 8
  • output
    3

对于上面的输入,解释如下。输入只包含一组测试数据,这组数据中有6个数,分别为0 2 5 5 4 8。输出结果为3。

  • 原始数据中模3余0的个数(C0 = 1)、余1的个数(C1 = 1)、余2的个数(C2 = 4),不相等,需要进行操作。
  • 第三个数加一【ans += 1】,数组变成0 2 6 5 4 8,C0 = 2、C1 = 1、 C2 = 3,不相等,继续操作。
  • 第六个数加一【ans += 1】,数组变成0 2 6 5 4 9,C0 = 3、C1 = 1、 C2 = 2,不相等,继续操作。
  • 第一个数加一【ans += 1】,数组变成1 2 6 5 4 9,C0 = 2、C1 = 2、 C2 = 2,相等,操作结束。
    操作结束之后,这组数据变成了1 2 6 5 4 9,其中C0 = 2、C1 = 2、 C2 = 2。

思路

其实题目在表述的时候已经给了我们一点思路,这个题没有什么完美的技巧可言,首先需要对读入的数据对3进行取模,因为每次只能在之中一个数上加1,那么就相当于将取模后的数移动了一位,就好比C0减1,那么C1必然加1;如果C1减1,那么C2必然加1;当C2减1,理所当然C0要加1。因为这个移动的过程是固定的,只能从前往后,所以我们就可以依次的进行枚举【最多只需要移动两步】,即可达到最优的操作,也就是最小的操作次数。

  • 这里只解释一种情况,其它的两种情况效果是一样的,可以类推.
  • 当C0大于数组个数的三分之一(N),我们需要把多的数移动到C1上,于是ans += C0 - N
  • 当C1 >= N时,同上,ans += C1 - N;
  • 当C1 < N时,这个时候我们的C1就只能由C2来贡献了,注意这时ans += 2 * (C2 - N)因为要移动两次。当这里三个数的个数就相等了。操作结束。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<bitset>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<algorithm>
#include<vector>
#define ll long long
#define ld long double
#define PI acos(-1.0)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define esp 1e-7
#define lowbit(x) x & (-x)

using namespace std;

const int maxx = 1e5 + 5;
const int MaxN = 1e7;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;

int n, m, T;
int l, r, ans;
int a[3];

int main(){
    
    
	int i, j, k;
	scanf("%d", &T);
	while( T-- ){
    
    
		ans = 0;
		memset(a, 0, sizeof a);
		scanf("%d", &n);
		for(i = 0; i < n; i++){
    
    
			scanf("%d", &k);
			a[k % 3]++;
		}
		n /= 3;
		if(a[0] >= n){
    
    
			a[1] += a[0] - n; ans += a[0] - n;
			if(a[1] >= n) ans += a[1] - n;
			else ans += 2 * (a[2] - n);
		}else if(a[1] >= n){
    
    
			a[2] += a[1] - n; ans += a[1] - n;
			if(a[2] >= n) ans += a[2] - n;
			else ans += 2 * (a[0] - n);
		}else if(a[2] >= n){
    
    
			a[0] += a[2] - n; ans += a[2] - n;
			if(a[0] >= n) ans += a[0] - n;
			else ans += 2 * (a[1] - n);
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/shangzhengyu/article/details/113855463