题目链接:https://ac.nowcoder.com/acm/contest/881/C

题目大意

  给定 m 和 n 个整数 ai,$-m \leq a_i \leq m$,求$\sum\limits_{i = 1}^{n} (\frac{a_i}{m} - p_i)^2$在约束条件$\sum\limits_{i = 1}^{n} p_i = 1, p_i \geq 0$下的最小值。

分析

  首先,为了方便计算,可以把 p 坐标都扩大 m 倍,最后结果除个 m2 即可。
  如此一来只需要算$\sum\limits_{i = 1}^{n} (a_i - p_i)^2$即可。
  根据 AM-GM 不等式(算术—几何均值不等式)(这里先假设$p_i \geq a_i 或者 p_i \leq a_i$):

$$\begin{align*}
\frac{\sum\limits_{i = 1}^{n} (a_i - p_i)^2}{n} \geq \sqrt[n]{\prod\limits_{i = 1}^{n} (a_i - p_i)^2} \\
当且仅当 p_1 - a_1 = p_2 - a_2 = \dots = p_n - a_n 时取等号。
\end{align*}$$

  于是可以得到关于 pi 的式子:$n(p_i - a_i) = m - \sum\limits_{i = 1}^{n} a_i$。
  于是答案就显而易见了。
  但问题是,由于约束条件,pi 并不会都大于 0 且都大于 $a_i$ 或小于 $a_i$,为了解决这个问题,我们先把 ai 从大到小排个序,然后利用上面的 AM-GM 不等式。
  然后我们发现以某个数 k 为分界,$p_1 \dots p_k$ 都是大于等于 0 的,而 $p_{k + 1} \dots p_n$ 都是小于零的。
  于是我们可以让 $p_{k + 1} \dots p_n$ 全部取 0,然后在 $[1, k]$ 上递归运用 AM-GM 不等式,直到找到一个区间,没有 $p_i$ 小于 0,而这个时候一定有$p_i \geq a_i 或者 p_i \leq a_i$(迷)。(具体可用二分法实现)
  
  那有没有可能 $p_{k + 1} \dots p_n$ 中选几个取一个大于 0 的值,答案能更小呢?这个我不晓得,也不会证,不过代码AC了,说明是没可能的。
  我的理解是,与其给自己,不如均摊。
  

  然后这边有大佬的解释:https://blog.nowcoder.net/n/1539da6d6d6e47a6998b5c6f5bba2167?tdsourcetag=s_pcqq_aiomsg

  思想其实和我一样,大佬解释为推平,推到推不下去为止。

  

  正解用了拉格朗日乘子法,但是写的太飘,解释的又太少,有些符号又看不懂什么意思,思维太跳,反正我是看不懂。

代码如下

 #include <bits/stdc++.h>
using namespace std; #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define Rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define rFor(i,t,s) for (int i = (t); i >= (s); --i)
#define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
#define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) #define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl #define LOWBIT(x) ((x)&(-x)) #define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define UNIQUE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define REMOVE(x, c) x.erase(remove(x.begin(), x.end(), c), x.end()); // ?? x ?????? c
#define TOLOWER(x) transform(x.begin(), x.end(), x.begin(),::tolower);
#define TOUPPER(x) transform(x.begin(), x.end(), x.begin(),::toupper); #define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,inf,sizeof(a))
#define msM(a) memset(a,-1,sizeof(a)) #define MP make_pair
#define PB push_back
#define ft first
#define sd second template<typename T1, typename T2>
istream &operator>>(istream &in, pair<T1, T2> &p) {
in >> p.first >> p.second;
return in;
} template<typename T>
istream &operator>>(istream &in, vector<T> &v) {
for (auto &x: v)
in >> x;
return in;
} template<typename T>
ostream &operator<<(ostream &out, vector<T> &v) {
Rep(i, v.size()) out << v[i] << " \n"[i == v.size()];
return out;
} template<typename T1, typename T2>
ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
out << "[" << p.first << ", " << p.second << "]" << "\n";
return out;
} inline int gc(){
static const int BUF = 1e7;
static char buf[BUF], *bg = buf + BUF, *ed = bg; if(bg == ed) fread(bg = buf, , BUF, stdin);
return *bg++;
} inline int ri(){
int x = , f = , c = gc();
for(; c<||c>; f = c=='-'?-:f, c=gc());
for(; c>&&c<; x = x* + c - , c=gc());
return x*f;
} template<class T>
inline string toString(T x) {
ostringstream sout;
sout << x;
return sout.str();
} inline int toInt(string s) {
int v;
istringstream sin(s);
sin >> v;
return v;
} //min <= aim <= max
template<typename T>
inline bool BETWEEN(const T aim, const T min, const T max) {
return min <= aim && aim <= max;
} typedef long long LL;
typedef unsigned long long uLL;
typedef pair< double, double > PDD;
typedef pair< int, int > PII;
typedef pair< int, PII > PIPII;
typedef pair< string, int > PSI;
typedef pair< int, PSI > PIPSI;
typedef set< int > SI;
typedef set< PII > SPII;
typedef vector< int > VI;
typedef vector< double > VD;
typedef vector< VI > VVI;
typedef vector< SI > VSI;
typedef vector< PII > VPII;
typedef map< int, int > MII;
typedef map< int, string > MIS;
typedef map< int, PII > MIPII;
typedef map< PII, int > MPIII;
typedef map< string, int > MSI;
typedef map< string, string > MSS;
typedef map< PII, string > MPIIS;
typedef map< PII, PII > MPIIPII;
typedef multimap< int, int > MMII;
typedef multimap< string, int > MMSI;
//typedef unordered_map< int, int > uMII;
typedef pair< LL, LL > PLL;
typedef vector< LL > VL;
typedef vector< VL > VVL;
typedef priority_queue< int > PQIMax;
typedef priority_queue< int, VI, greater< int > > PQIMin;
const double EPS = 1e-;
const LL inf = 0x7fffffff;
const LL infLL = 0x7fffffffffffffffLL;
const LL mod = 1e9 + ;
const int maxN = 1e4 + ;
const LL ONE = ;
const LL evenBits = 0xaaaaaaaaaaaaaaaa;
const LL oddBits = 0x5555555555555555; LL n, m, a[maxN], preSum[maxN], ans; int main(){
//freopen("MyOutput.txt","w",stdout);
//freopen("input.txt","r",stdin);
//INIT();
while(~scanf("%lld %lld", &n, &m)) {
For(i, , n) scanf("%lld", &a[i]);
sort(a + , a + n + , greater< LL >()); For(i, , n) preSum[i] = a[i] + preSum[i - ]; int l = , r = n;
while(l < r) {
int mid = (l + r) >> ; if(m - preSum[mid + ] + (mid + ) * a[mid + ] >= ) l = mid + ;
else r = mid;
}
ans = (m - preSum[l]) * (m - preSum[l]) * l;
For(i, l + , n) ans += a[i] * a[i] * l * l; LL x = m * m * l * l;
LL d = __gcd(ans, x);
ans /= d;
x /= d;
if(x == ) printf("%lld\n", ans);
else printf("%lld/%lld\n", ans, x);
}
return ;
}
/*
7 16
4 9 -4 -6 -3 5 13
469/1024 8 16
4 9 -4 -6 -3 5 13 7
79/128
*/

2019 牛客多校第一场 C Euclidean Distance ?的更多相关文章

  1. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

  2. 2019牛客多校第一场E ABBA(DP)题解

    链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...

  3. 2019牛客多校第一场A-Equivalent Prefixes

    Equivalent Prefixes 传送门 解题思路 先用单调栈求出两个序列中每一个数左边第一个小于自己的数的下标, 存入a[], b[].然后按照1~n的顺序循环,比较 a[i]和b[i]是否相 ...

  4. 2019牛客多校第一场 A.Equivalent Prefixes

    题目描述 Two arrays u and v each with m distinct elements are called equivalent if and only if RMQ(u,l,r ...

  5. 2019 牛客多校第一场 D Parity of Tuples

    题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...

  6. 2019牛客多校第一场 E-ABBA(dp)

    ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...

  7. 【2019牛客多校第一场】XOR

    题意: 给你一个集合A,里边有n个正整数,对于所有A的.满足集合内元素异或和为0的子集S,问你∑|S| n<=1e5,元素<=1e18 首先可以转化问题,不求∑|S|,而是求每个元素属于子 ...

  8. 2019 牛客多校第一场 B Integration

    题目链接:https://ac.nowcoder.com/acm/contest/881/B 题目大意 给定 n 个不同的正整数 ai,求$\frac{1}{\pi}\int_{0}^{\infty} ...

  9. 2019牛客多校第一场E ABBA 贪心 + DP

    题意:问有多少个有(n + m)个A和(n + m)个B的字符串可以凑出n个AB和m个BA. 思路:首先贪心的发现,如果从前往后扫,遇到了一个A,优先把它看成AB的A,B同理.这个贪心策略用邻项交换很 ...

随机推荐

  1. 【Flutter学习】基本组件之容器组件Container

    一,前言 Flutter控件本身通常由许多小型.单用途的控件组成,结合起来产生强大的效果,例如,Container是一种常用的控件,由负责布局.绘画.定位和大小调整的几个控件组成,具体来说,Conta ...

  2. Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)

    题目:http://codeforces.com/contest/1185/problem/G1 题意:给你n给选项,每个选项有个类型和价值,让你选择一个序列,价值和为m,要求连续的不能有两个相同的类 ...

  3. (转)深刻理解Linux进程间通信(IPC)

    转:http://www.ibm.com/developerworks/cn/linux/l-ipc/index.html 序 linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来 ...

  4. Codeforces Round#498(Div.3)D. Two Strings Swaps

    题目 题意是给了两个字符串a和b,然后可以对这两个字符串有三种操作来使这两个字符串相等,一是交换a[i]和b[i],二是交换a[i]和a[n-i+1],三是交换b[i]和b[n-i+1],这三个操作都 ...

  5. fatal error C1076: compiler limit : internal heap limit reached; use /Zm to specify a higher limit

    最近想用一下Xtreme ToolkitPro 界面库,安装后用VC6根据向导 产生一个工程,编译时出现如下的错误: fatal error C1076: compiler limit : inter ...

  6. C#之winform 猜拳小游戏

    C#之winform 猜拳小游戏 1.建立项目文件 2.进行界面布局 2.1 玩家显示(控件:label) 2.2  显示玩家进行选择的控件(控件:label) 2.3 电脑显示(控件:label) ...

  7. 剑指offer——570~n-1中缺失的数字

    题目:0~n-1中缺失的数字. 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内. 在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字. ...

  8. ajaxFileUpload.js插件支持多文件上传的方法

    前提条件:ajaxFileUpload.js插件多文件上传步骤:1.修改源码,(源码只支持单个文件的上传):复制代码 代码如下: //修改前代码------- //var oldElement = j ...

  9. CSS Sprite初探之原理、使用

    CSS Sprite简介: 利用CSS Sprites能很好地减少了网页的http请求次数,从而大大的提高了页面的性能,节省时间和带宽.CSS Sprites在国内很多人叫css精灵, 是一种网页图片 ...

  10. python去除rpm仓库中同名低版本的包

    编程思路1 遍历目标路径的rpm包并保存特性包列表: 2 利用python模块rpmUtils提取RPM包的特征信息:包名  版本号 架构 3 遍历特性列表中存在重复包名的rpm, 将低版本的rpm包 ...