P4016题解

本题是一个比较经典的问题(环形均分纸牌问题),我也不知道为什么它在网络流 24 题里面出现。但是作为一道比较典的排序算法的题,还是放出来讲一下。

solution

假设 a1anx1 张纸牌,a2a1x2 张纸牌......( xi 可正可负)。

因此操作数量为 |x1|+|x2|+|xn|

a=a1+a2++ann

因此可以列出下面的式子:

{a1x1+x2=aa2x2+x3=aanxn+x1=a

将所有式子加起来,会发现是一个恒等式,因此不具有唯一解。

将方程进行等价代换:

{x1x2=a1ax2x3=a2axn1xn=an1axnx1=ana

x1 为自由变量,来表示其他变量

{x1=x10x2=x1(a1a)x3=x1(a1+a22a)xn=x1[a1+a2++an1(n1)a]

后面的一堆 a 都为常数,记为 Ci

因此看最上面 |x1|+|x2|+|xn| 的式子,就可以转化为 |x1C1|+|x1C2|++|x1Cn|

将其看作数轴上的一堆点:

可以将 x1 取作中位数能将操作次数最小化

  • 证明:

绝对值不等式: |a|+|b||a+b|

假设 C 序列已排好序,将上式分组为 (|x1C1|+|Cnx1|)+(|x1C2|+|Cn1x1|)|CnC1+Cn1C2+Cn2C3++Cn+12x1|

因此令 x1 取到中位数即可

完整代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e6 + 10;
ll a[N], c[N], avg;
ll n;

int main()
{
    scanf("%lld", &n);
    avg = 0;
    for(int i = 1; i <= n; i ++ ) 
    {
        cin >> a[i];
        avg += a[i];
    }

    avg /= n;
    c[1] = 0;
    for(int i = 2; i <= n; i ++ ) c[i] = c[i - 1] + a[i] - avg;

    sort(c + 1, c + n + 1);
    ll res = 0;
    for(int i = 1; i <= n; i ++ ) res += abs(c[i] - c[(n + 1) / 2]);

    cout << res << endl;

    return 0;
}

PS:经验

posted @   crimson000  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示