BZOJ 1045 HAOI 2008 糖果传递 数学推导

好像Chrome支持MathJax有点问题。。Microsoft Edge一点事没有。。
因为一个一个小朋友传递,所以只用考虑两相邻两个小朋友间的关系。
xi 表示小朋友 i1 i 的糖果数, v=1nai ,那么显然有:

ans=|xi|

而且对于每个小朋友有:
v=ai+xixi+1

因此
xi+1=xi+aiv

因此, {xi} 之间存在一个关系,使得某个 xi 定下来了以后,其他 xj 都确定了,因而答案 ans 也确定了。
假设我们固定 x1 ,那么对于其他数字,如
x2x3=x1+a1v=x2+a2v=x1+a1v+a2v

我们设 c0=0,ci=ci1ai+v ,那么有
xi=x1ci

答案有
ans=|x1c0|+|x1c1|+|x1c2|++|x1cn1|

发现这个式子表示的就是 x1 在数轴上与 ci 的距离和,要使距离和最小,就要使 x1=ci 的中位数,问题就解决了。

发的时候用I64d跪了。。。

#include 
#include 
#include 
using namespace std;
typedef long long ll;
#define FOR(i,j,k) for(i=j;i<=k;i++)
const int N = 10000005;

ll read() {
    ll s = 0, f = 1; char ch = getchar();
    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
    return s * f;
}

int main() {
    static int a[N], s[N];
    ll n = read(), i, x, tot = 0, avg, mid, ans;
    s[0] = 0;
    FOR(i,1,n) a[i] = read(), tot += a[i];
    avg = tot / n;
    FOR(i,1,n-1) s[i] = s[i - 1] + a[i] - avg;
    sort(s + 1, s + n);
    mid = s[n / 2];
    ans = abs(mid);
    FOR(i,1,n-1) ans += abs(s[i] - mid);
    printf("%lld\n", ans);
    return 0;
}

1045: [HAOI2008] 糖果传递

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3047 Solved: 1378

Description

有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。

Input

小朋友个数n 下面n行 ai

Output

求使所有人获得均等糖果的最小代价。

Sample Input

4
1
2
5
4

Sample Output

4

HINT

100% n<=987654321

你可能感兴趣的:(BZOJ,——数学——)