P2512 [HAOI2008]糖果传递(环形“均分纸牌“可链化,前缀和数组)

P2512 [HAOI2008]糖果传递

均分纸牌题解

题意: n n n个人,每个人有 A i A_i Ai颗糖果,第 i i i人给第 i − 1 i-1 i1 X i X_i Xi颗糖果(第一人给第 n n n人, X i X_i Xi可正可负,负数表示第 i − 1 i-1 i1个给第i人),设平均值为 a v e ave ave,每给一颗糖果记为一次操作,问最少操作次数使n个人的糖果数量最少。

  ~  
  ~  

参考大佬博客F_J

主要证明(复述):

a v e = A 1 + X 2 − X 1 ave = A_1 + X_2 - X_1 ave=A1+X2X1
a v e = A 2 + X 3 − X 2 ave = A_2 + X_3 - X_2 ave=A2+X3X2
……
a v e = A n + X 1 − X n ave = A_n+ X_1 - X_n ave=An+X1Xn
= = > ==> ==>

X 2 = X 1 − ( A 1 − a v e ) X_2 = X_1-(A_1-ave) X2=X1(A1ave)
X 3 = X 1 − ( A 1 + A 2 − a v e ∗ 2 ) X_3 = X_1-(A_1+A_2-ave*2) X3=X1(A1+A2ave2)
……
X n = X 1 − ( A 1 + A 2 . . . . . . A n − a v e ∗ ( n − 1 ) ) X_n = X_1-(A_1+A_2......A_n-ave*(n-1)) Xn=X1(A1+A2......Anave(n1))

S i = ∑ i = 1 n A [ i ] − a v e S_i = \sum_{i=1}^{n}{A[i]-ave} Si=i=1nA[i]ave
= = > ==> ==>

X 2 = X 1 − S 1 X_2 = X_1-S_1 X2=X1S1
X 3 = X 1 − S 2 X_3 = X_1-S_2 X3=X1S2
……
X n = X 1 − S n X_n = X_1-S_n Xn=X1Sn

操作次数就是:

a n s = ∑ i = 1 n X i = ∑ i = 1 n ∣ X 1 − S i ∣ ans = \sum_{i=1}^nX_i = \sum_{i=1}^{n} \mid X_1-S_i\mid ans=i=1nXi=i=1nX1Si

那么原问题变成了求 X1 的值使得上述求和最小,上述求和可以看作是求点到直线的距离。
先将 S 数组从小到大排序。
如果 n 为奇数,那么 X1=Sn/2+1
如果 n 为偶数,那么 X1∈[Sn/2,Sn/2+1]
可以发现,不论 n 为奇数还是偶数,X1 都可以取到S 数组中的某个值使得求和最小,因此存在某个 Xi=X1−Si=0,即有两个人之间没有纸牌传递,因此这种解法实际上证明了环形均分纸牌问题的可链化。

结论:
我们取数组 b [ i ] = A i − a v e b[i]=A_i-ave b[i]=Aiave的前缀和数组 s u m [ i ] sum[i] sum[i]的中值为 X 1 X_1 X1,求出最小操作次数。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
ll s[N], sum[N];
int main() {
    ll n, ave = 0;
    cin >> n;
    for(int i=1; i<=n; i++) {
        cin >> s[i]; ave += s[i];
    }
    ave /= n;
    for(int i=1; i<=n; i++) {
        s[i] -= ave; sum[i] = sum[i-1] + s[i];
    }
    sort(sum+1, sum+1+n);
    ll mid = (1+n)/2, ans = 0;
    for(int i=1; i<=n; i++) {
         ans += abs(sum[mid] - sum[i]);
    }
    cout << ans;
    return 0;
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值