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;
}