环形均分纸牌问题

这类题目很套路 也很简单

下面我大概阐述一下思路

对于\(n\)个人,不妨假设每个人都有一个权值\(P_i\)

这个\(P_i\)支持转移 转移法则支持加法,减法法则

即 对于 第\(i\)个人我们可以选择

\(\forall v\in[0,P_i]s.t. v\in Z\Rightarrow P_i -=v,P_{i-1}+=v|P_{i+1}+=v\)

针对这类问题

我定义\(f_i\)表示第\(i\)个人进行了\(v=f_i\)的操作

那么 可得

\[f_i=f_1-(S_i-w*i)\]

\[S_i=\displaystyle\sum_{j=1}^iP_j\]

\[w=\frac{\displaystyle\sum_{j=1}^nP_j}{n}\]

\[C_i=S_i-w*i\]
然后就相当于

\[ans =\displaystyle\sum_{j=1}^nf_j=\displaystyle\sum_{j=1}^n|f_1-C_i|\]

相当于在数轴上求一点使得它到其它点的距离之和最小

\(Code\)

例题P2512 [HAOI2008]糖果传递

#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define reg register int
#define isdigit(x) ('0' <= x&&x <= '9')
template<typename T>
inline T Read(T Type)
{
    T x = 0,f = 1;
    char a = getchar();
    while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();}
    while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();}
    return x * f;
}
const int MAXN = 1e6 + 10;
typedef long long ll;
ll a[MAXN],sum[MAXN],b[MAXN],n,fre,ans;
inline ll fabs(ll x) {return (x < 0?-x:x);}
int main()
{
    n = Read(1);
    for(reg i = 1;i <= n;i++) a[i] = Read(1),fre += a[i];
    fre /= n;
    for(reg i = 1;i <= n;i++)
    {
        sum[i] = sum[i - 1] + a[i];
        b[i] = i * fre - sum[i];
    }
    sort(b + 1,b + 1 + n);
    ll mina = b[n / 2],ans = 0;
    for(reg i = 1;i <= n;i++)
        ans += fabs(mina - b[i]);
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/resftlmuttmotw/p/11865494.html
今日推荐