【题解】AT_abc313_c 题解
1.【题解】ABC388F Dangerous Sugoroku2.【题解】AT_abc256_f 题解
3.【题解】AT_abc313_c 题解
4.【题解】AT_abc298_c 题解5.【题解】AT_abc295_c 题解6.【题解】AT_abc293_d 题解7.【题解】AT_abc292_c 题解8.【题解】AT_abc291_c 题解9.【题解】AT_abc290_c 题解10.【题解】AT_abc289_c 题解11.【题解】AT_abc288_c 题解12.【题解】AT_abc280_b 题解13.【题解】AT_abc277_a 题解14.【题解】AT_abc276_c 题解15.【题解】AT_joi2012yo_a题解16.【题解】AT yahoo procon2017 qual a题解17.ABC396F 题解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; }
本文作者:邻补角の杂货铺
本文链接:https://www.cnblogs.com/sslbj/p/18708396
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步