题意:给你一个大小为n的数组,m是n的一个divisor。每次可以对ai+1,问最少的次数让数组中的每个元素除m 的余数 从0到m-1 各有n/m个。
题解:贪心思想如果余数要加,那么能加最少就加最少,我找出要加到最少的目标余数进而就可以的出这一次的操作次数,然后该元素也会做出相应改变。具体看代码。
重点用到了三个我不会的set函数:set.rbegin()返回set中最大的元素,set.begin()返回最小元素,set.lowerbound(int x)二分返回大于等于x的第一个元素。
AC代码:
#include <iostream>
#include <set>
using namespace std;
const int maxn=2e5+6;
typedef long long ll;
ll n,m,a[maxn],num[maxn],ans;
set<int>s;
int main(){
ios::sync_with_stdio(false);
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;//x代表我要加到目标余数
//贪心思想,寻找d所能加到的最近的余数
if(d>*s.rbegin())x=*s.begin();//d比最大的余数还大 ,贪心,一直加到最小的余数就行
else x=*s.lower_bound(d);//d就在余数范围内,找到大于等于d的第一个余数
if(++num[x]==n/m)s.erase(x);//凑够了,删去对应的余数
ans+=(x-d+m)%m;
a[i]+=(x-d+m)%m;//元素发生相应改变
}
cout<<ans<<endl;
for(int i=0;i<n;i++)cout<<a[i]<<" ";
}