【题解】AT_abc313_c 题解
AT_abc313_c 题解
思路分析
简单推柿子的题。
我们要如何使得这个数列的最大值与最小值的差为 呢?显然是要尽可能的去让数列中的数平均分布。
显然,当两个数一个加 ,一个减 时,两数和不变。又因为每次都是这样的操作,因此操作完毕后数列总和不变。
设数列总和为 ,数列中有 个数。则尽可能平均时,情况如下:
- 后 个数为 。
- 余下的前面的数为 。
然后,我们求出操作次数。
设两数原为 与 ,要变为 与 ( 且 )。由题意,,即 。
设 。
由于两者要变化的量 相同,因此,只需操作 次即可。如何计算 呢?由 的定义,,即 ,。
还有,由于我们要满足条件 ,因此要对数列排序。而 是天然满足的,因此不用排序。
最后,由于该情况是最平均的情况,所以操作至此情况所需的步骤也最小。因此按照上述步骤实现即可。
代码
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define int long long
#define IL inline
using namespace std;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
IL int read()
{
int x = 0,f = 1;
char c = getchar();
while(c <'0'|| c >'9'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
return x * f;
}
void write(int x)
{
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int a[N], b[N];
signed main()
{
int n;
cin >> n;
int s = 0; //和
for(int i = 1;i <= n;i++)
{
cin >> a[i];
s += a[i];
}
sort(a + 1, a + n + 1);
for(int i = 1;i <= n - s % n;i++) //余下的前面的数为 floor(s/n)
{
b[i] = s / n;
}
for(int i = 1;i <= s % n;i++) //后 s % n 个数为 ceil(s/n)(即floor(s / n) + 1)
{
b[n - i + 1] = s / n + 1;
}
//依照公式计算操作次数
int ans = 0;
for(int i = 1;i <= n;i++)
{
ans += abs(b[i] - a[i]);
}
cout << ans / 2 << endl;
return 0;
}

浙公网安备 33010602011771号