传送门:NOIP2021 T3

作者是一个考场上没做出来的蒟蒻

题目大意

  给你一个长度为 nnn 的数组 a1,a2,a3,⋯,ana_1, a_2, a_3, \cdots, a_na1​,a2​,a3​,⋯,an​,这个数列是非严格单调递增的。然后我们可以对这个数组进行一种神奇的操作:选择一个数 aia_iai​,然后 ai=ai+1+ai−1−aia_i = a_{i+1} + a{i-1} - a_iai​=ai+1​+ai−1−ai​。问进行若干次(随便多少次)操作之后这个数列的方差的最小值是多少

分析

  看题,贪心?算出每一次操作对方差的贡献,然后每次取贡献最小的来操作。反正不知道怎么证明正确性,先打出来再说。然后一测样例,很好,错的。

  然后怎么办呢,考场上我就没想出来了。等考完之后,我听机房里的几个大佬在讨论的时候说这个玩意儿的差分有一些神秘的性质,然后我下来就试着分析了一下,然后居然真的有一些神秘的性质。

  首先很显然,因为这个 aaa 数组是非严格单调递增的,所以差分数组中(差分记为 ccc)∀ci≥0\forall c_i \geq 0∀ci​≥0。然后我们考虑对 aaa 数组进行一次操作,也就是改变一个数:

ai−1,ai,ai+1→ai−1,ai−1+ai+1−ai,ai+1a_{i-1}, a_{i}, a_{i+1} \to a_{i-1}, a_{i-1} + a_{i+1} - a_i, a_{i+1} ai−1​,ai​,ai+1​→ai−1​,ai−1​+ai+1​−ai​,ai+1​

  然后这三个位置的差分数组就会发生变化,首先原来的差分数组是这样:

ci−1=ai−1−ai−2ci=ai−ai−1ci+1=ai+1−aic_{i-1} = a_{i-1} - a_{i-2}\\ c_{i} = a_{i} - a_{i-1}\\ c_{i+1} = a_{i+1} - a_{i}ci−1​=ai−1​−ai−2​ci​=ai​−ai−1​ci+1​=ai+1​−ai​

  所以这三个位置的差分就是:

ai−1−ai−2,ai−ai−1,ai+1−aia_{i-1} - a_{i-2}, a_{i} - a_{i-1}, a_{i+1} - a_{i} ai−1​−ai−2​,ai​−ai−1​,ai+1​−ai​

  进行操作之后就有:

ci−1′=ai−1′−ai−2′=ai−1−ai−2=ci−1ci′=ai′−ai−1′=ai−1+ai+1−ai−ai−1=ai+1−ai=ci+1ci+1′=ai+1′−ai′=ai+1−(ai−1+ai+1−ai)=ai−ai−1=cic'_{i-1} = a'_{i-1} - a'_{i-2} = a_{i-1} - a_{i-2} = c_{i-1}\\ c'_{i} = a'_{i} - a'_{i-1} = a_{i-1} + a_{i+1} - a_i - a_{i-1} = a_{i+1} - a_i = c_{i+1}\\ c'_{i+1} = a'_{i+1} - a'_{i} = a_{i+1} - (a_{i-1} + a_{i+1} - a_i) = a_i - a_{i-1} = c_i ci−1′​=ai−1′​−ai−2′​=ai−1​−ai−2​=ci−1​ci′​=ai′​−ai−1′​=ai−1​+ai+1​−ai​−ai−1​=ai+1​−ai​=ci+1​ci+1′​=ai+1′​−ai′​=ai+1​−(ai−1​+ai+1​−ai​)=ai​−ai−1​=ci​

  也就是说,新的差分数组就是这样:

ci−1,ci+1,cic_{i-1}, c_{i+1}, c_i ci−1​,ci+1​,ci​

  然后就会发现,现在的差分数组就是在原差分数组的基础上交换了 iii 和 i+1i+1i+1 两个位置的数。也就是说,每一次操作只会改变差分数组的排列顺序,不会在差分数组里产生原来没有出现过的数。那么我们根据这一点,就能很容易想到一种 O(n⋅(n−1)!)O(n \cdot (n-1)!)O(n⋅(n−1)!) 的暴力算法,就是先把原数组的差分数组算出来,然后对 2∼n2 \sim n2∼n 的位置求全排列(差分数组的第一个位置始终不变),然后再对每一个差分数组的原数组求出方差再取最小值就可以了。

  当然,我们可以对方差的计算公式稍微简化一下:
σ2=1n∑i=1n(ai−a‾)2,a‾=1n∑i=1nai=1n∑i=1nai2+1n∑i=1na‾2−1n∑i=1naia‾=1n∑i=1nai2+a‾2−2a‾2=1n∑i=1nai2−a‾2=1n∑i=1nai2−(1n∑i=1nai)2\begin{aligned} \sigma^2 = & \frac 1n\sum_{i=1}^n (a_i - \overline{a})^2, \quad \overline{a} = \frac 1n\sum_{i=1}^n a_i \\ = & \frac 1n\sum_{i=1}^na_i^2 + \frac 1n\sum_{i=1}^n\overline{a}^2 - \frac 1n\sum_{i=1}^na_i\overline{a} \\ = & \frac 1n\sum_{i=1}^n a_i^2 + \overline{a}^2 -2\overline{a}^2 \\ = & \frac 1n\sum_{i=1}^n a_i ^ 2 - \overline{a}^2 = \frac 1n\sum_{i=1}^n a_i^2 - (\frac 1n\sum_{i=1}^n a_i)^2 \\ \end{aligned} σ2====​n1​i=1∑n​(ai​−a)2,a=n1​i=1∑n​ai​n1​i=1∑n​ai2​+n1​i=1∑n​a2−n1​i=1∑n​ai​an1​i=1∑n​ai2​+a2−2a2n1​i=1∑n​ai2​−a2=n1​i=1∑n​ai2​−(n1​i=1∑n​ai​)2​

  题目要求的答案也就是:
ans=n2σ2=n∑i=1nai2−(∑i=1nai)2ans = n^2 \sigma^2 = n\sum_{i=1}^n a_i^2 - (\sum_{i=1}^n a_i)^2 ans=n2σ2=ni=1∑n​ai2​−(i=1∑n​ai​)2

  用这种暴力的方法可以得 20 分。

  如果想要得到更高的分数那么我们可以考虑找一找方差数组在最优解中都有没有一些神秘的规律。首先题目的要求是让我们弄出来的数组的方差是最小的,于是我们根据方差的一些性质就能知道我们要求把数组中每个数之间的 “差异度” 调到最小(因为数组的方差就是数组离散程度的度量嘛)。如果要满足数组中数的差异最小,方差会长成什么样子呢?

  别忘了我们这个数组还有一个性质,也就是它非严格单调递增也就是 a1≤a2≤⋯≤ana_1 \leq a_2 \leq \cdots \leq a_na1​≤a2​≤⋯≤an​。所以对于这个数组的方差来说 ∀ci≥0\forall c_i \geq 0∀ci​≥0。因此就有一种很显然的构造方法就是让差分数组是一个 “单谷数列”。什么意思呢,就是说 c1≥c2≥⋯≥ci≤ci+1≤⋯≤cnc_1 \geq c_2 \geq \cdots \geq c_i \leq c_{i+1} \leq \cdots \leq c_nc1​≥c2​≥⋯≥ci​≤ci+1​≤⋯≤cn​。因为如果你把这个数列的各个点在平面直角坐标系里画出来,再用平滑曲线连接各个点就会得到一个像山谷一样的图像,所以就叫它 单谷数列

  这个性质的证明也很简单,假设现在方差已经是一个单谷数列了,那么我们在这个方差的谷底的右侧(左侧同理)施加一个扰动,使得这个方差数组不再是单谷数列,也就是选择一个下标 iii,并且交换 cic_ici​ 和 ci+1c_{i+1}ci+1​ 在差分数组中的位置。那么我们会发现这次由这个差分所对应的原数组从位置 iii 开始就一定比由单谷的差分对应的原数组中的数要大(因为 ci+1≥cic_{i+1} \geq c_{i}ci+1​≥ci​)。所以新的数组的 “差异度” 就比之前的那个要大,所以方差也就比原来的数组大。

  所以只有差分是单谷数列的时候才能做到方差最小。

  那么我们就比较容易找到一种更优秀的做法。

  我们设差分数组为 {di}\{d_i\}{di​},这个差分对应的原数组为 {ai}\{a_i\}{ai​}。我们把 ddd 数组从小到大排序,然后考虑从小到大依次加入。因为我们知道我们要构造的东西是单谷的,所以我们只用考虑每次加在已经有的序列的两端。 然后又考虑到刚才我们弄出来的差分的式子要最小化:

ans=n∑i=1nai2−(∑i=1nai)2ans = n\sum_{i=1}^n a_i^2 - (\sum_{i=1}^n a_i)^2 ans=ni=1∑n​ai2​−(i=1∑n​ai​)2

  答案最小化就是要在最小化 n∑i=1nai2n\sum\limits_{i=1}^n a_i^2ni=1∑n​ai2​ 的同时最大化 (∑i=1nai)2(\sum\limits_{i=1}^n a_i)^2(i=1∑n​ai​)2,所以我们考虑这样设置 dpdpdp 的状态,设 fi,xf_{i, x}fi,x​ 表示当前考虑加入第 iii 个差分,现在的 ∑iai=x\sum\limits_ia_i = xi∑​ai​=x 的最小的平方和。那么就只有两种情况:

  1. 加在左边,那么现在的所有数都要加上 did_idi​,所以对答案的贡献就是 2xdi+idi22xd_i + id_i^22xdi​+idi2​,并且转移到 fi+1,x+idif_{i + 1, x + id_i}fi+1,x+idi​​。

fi,x+2xdi+idi2→fi+1,x+idif_{i, x} + 2xd_i + id_i^2 \to f_{i + 1, x + id_i} fi,x​+2xdi​+idi2​→fi+1,x+idi​​

  1. 加在右边,现有的数不会变,令 si=∑k=1idks_i = \sum\limits_{k = 1}^i d_ksi​=k=1∑i​dk​,那么贡献就是 si2s_i^2si2​,并且转移到 fi+1,x+sif_{i + 1, x + s_i}fi+1,x+si​​

fi,x+si2→fi+1,x+sif_{i, x} + s_i^2 \to f_{i + 1, x + s_i} fi,x​+si2​→fi+1,x+si​​

  初始化就是 f1,0=0,fi,x=INFIf_{1, 0} = 0, f_{i, x} = INFIf1,0​=0,fi,x​=INFI,答案就是:

ans=min⁡x=0mx{nfn,x−x2}ans = \min_{x = 0}^{mx} \{ nf_{n, x} - x^2 \} ans=x=0minmx​{nfn,x​−x2}

  其中 mxmxmx 是 dpdpdp 过程中记录的最大的 ∑iai\sum\limits_{i}a_ii∑​ai​。

代码

  全排列暴力 20 分:

#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 100100
#define INFI 1 << 30
#define endl '\n'inline int read(){int x = 0; char c = getchar();while(c < '0' or c > '9') c = getchar();while('0' <= c and c <= '9'){x = x * 10 + c - '0'; c = getchar();}return x;
}int n = 0;
int a[MAXN] = { 0 };
int c[MAXN] = { 0 };int ans = INFI;
int na[MAXN] = { 0 };
int nc[MAXN] = { 0 };
int vis[MAXN] = { 0 };void work(){for(int i = 1; i <= n; i++) na[i] = na[i-1] + nc[i];int res = 0; int sum = 0;for(int i = 1; i <= n; i++){res += na[i] * na[i]; sum += na[i];}res *= n; res -= sum * sum;ans = min(ans, res);
}void dfs(int now){if(now > n){ work(); return; }for(int i = 1; i <= n; i++){if(!vis[i] and ((now == 1 and i == 1) or (now != 1 and i != 1))    ){nc[now] = c[i]; vis[i] = 1;dfs(now + 1);nc[now] = 0; vis[i] = 0;}}
}int main(){n = in;for(int i = 1; i <= n; i++) a[i] = in;for(int i = 1; i <= n; i++) c[i] = a[i] - a[i-1];dfs(1);cout << ans << endl;return 0;
}

  100pts100 pts100pts 的 dpdpdp。

#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 10010
#define MAXM 500500
#define INFI 1 << 30inline int read(){int x = 0; char c = getchar();while(c < '0' or c > '9') c = getchar();while('0' <= c and c <= '9'){x = x * 10 + c - '0'; c = getchar();}return x;
}int n = 0;
int a[MAXN] = { 0 };
int d[MAXN] = { 0 };
int s[MAXN] = { 0 };
int f[MAXM] = { 0 }; int main(){n = in; int maxa = 0, mx = 0, ans = INFI;for(int i = 1; i <= n; i++) a[i] = in, maxa = max(maxa, a[i]);for(int i = 1; i <= n; i++) d[i] = a[i + 1] - a[i];for(int i = 1; i <= n * maxa; i++) f[i] = INFI; f[0] = 0; sort(d + 1, d + n);for(int i = 1; i < n; i++){s[i] = s[i - 1] + d[i];if(d[i] == 0) continue;for(int x = mx; x >= 0; x--){if (f[x] == INFI) continue;f[x + i * d[i]] = min(f[x + i * d[i]], f[x] + 2 * x * d[i] + i * d[i] * d[i]);f[x + s[i]] = min(f[x+ s[i]], f[x] + s[i] * s[i]);mx = max(mx, max(x + i * d[i], x + s[i]));f[x] = INFI;}}for(int i = 0; i <= mx; i++)if(f[i] < INFI) ans = min(ans, n * f[i] - i * i);cout << ans << '\n';return 0;
}

NOIP2021 T3 方差相关推荐

  1. 分组数据方差公式_连续变量假设检验 之 单因素方差检验

    单因素方差分析概述 单因素设计方差分析也称之为一维方差分析,是研究一个研究因素不同水平(K ≥3)间的计量变量比较,也就是用于检验一个因素取不同水平时某因变量均值是否有显著变化.在进行分析同时,还可进 ...

  2. NOIP2021总结

    前言 不得不说,noip2021还是较为友好的,虽然自己答的稀碎挂一堆分但还是侥幸没有AFO 考试过程 騲 进教学楼心态就炸了 忘带核酸报告辣,dayu帮打的( 感动 进错考场辣,各种证件协议交错老师 ...

  3. NOIP2021游记

    高二了,最后一次参加noip了,AFO 人均过T1,只有我没有切掉qwq,数组没有开到1e7,只开到了2e5,只得到了70pts T2由于没有足够的dp能力,只想到了朴素的状压dp做法,得到了50pt ...

  4. 常用概率分布的矩母函数、特征函数以及期望、方差的推导

    常用概率分布的矩母函数.特征函数以及期望.方差的推导 一.定义与性质 二.离散型随机变量的分布 0.退化分布(Degenerate distribution) 1.离散型均匀分布(Discrete u ...

  5. NOIP2021 游记

    Day -? 考了无数次模拟,名次有些起伏,有时候会垫底,有时候又会冲到前面去 不过还没有爆过零,这是好的 帅帅还布置了两份线段树进阶的题单,我只刷穿了一份,其中还咕掉一道线段树模拟费用流的毒瘤题,另 ...

  6. IMU标定之---Allan方差

    0. 简介 在研究晶体振荡器和原子钟的稳定性时,人们发现这些系统的相位噪声中不仅有白噪声,而且有闪烁噪声.使用标准差分析这类噪声时发现结果是无法收敛的.为了解决这个问题,David Allan于196 ...

  7. 神经网络的偏差和方差,神经网络均方误差公式

    1.你好,想跟你要一下神经网络的代码,看到你之前解答过问题,谢谢了 // BP.cpp : Defines the entry point for the console application. / ...

  8. 洛谷 P7960 [NOIP2021] 报数

    PS:如果读过题了可以跳过题目描述直接到题解部分 提交链接:洛谷 P7960 [NOIP2021] 报数 题目 题目描述 报数游戏是一个广为流传的休闲小游戏.参加游戏的每个人要按一定顺序轮流报数,但如 ...

  9. 标准差 方差 协方差 相关系数

    一.统计学的基本概念 统计学里最基本的概念就是样本的均值.方差.标准差.首先,我们给定一个含有n个样本的集合,下面给出这些概念的公式描述: 均值: 标准差: 方差: 均值描述的是样本集合的中间点,它告 ...

最新文章

  1. AngularJS快速入门
  2. tf.variable_scope与tf.tf.get_variable
  3. Bzoj 2724: [Violet 6]蒲公英(分块)
  4. 补发《超级迷宫》站立会议三
  5. 自己做计算机三级,计算机三级辅导:自己“做”软驱
  6. 牛客14607 递推(矩阵快速幂构造)
  7. 使用 ADB LogCat 查看在Android真机上 Unity debug.log 输出日志
  8. Go1.17 这个新特性竟是 6 年前提出来的
  9. linux自动分区shell,SHELL脚本实现分区
  10. linux下彻底卸载mysql 图解教程
  11. Other - 个人对知识讨论、分享等平台上抄袭乱象的看法
  12. 【b站黑马程序员C++视频学习笔记-文件操作】
  13. js基础(2)~元素增删,属性,节点,定时器,date,事件,模块
  14. CAML: FAST CONTEXT ADAPTATION VIA META-LEARNING
  15. Android TV 开发之 TV视频播放器
  16. 分布式和集中式版本控制工具-svn,git,mercurial比较分析
  17. powerDesigner 反向生成mysql数据库库
  18. adobe服务器无响应,链接不到adobe服务器
  19. 风之谷mobi-宫崎骏漫画kindle7本
  20. git 公钥配置时问题解决记录

热门文章

  1. XEN的启动信息输出到“Platform timer is 14.318MHz HPET”就暂停接收的解决办法
  2. 2022 哪些企业在考虑 IDaaS ?IDaaS 适合我们企业么?
  3. 2021漳州一中历年高考成绩查询,2021年漳州中考录取分数线,历年漳州各高中录取分数线排名...
  4. python anaconda下载包_anaconda python 2.7
  5. 【ESP8266 ES01 小爱】使用ESP 8266 WOL 远程唤醒电脑
  6. 英特尔安腾服务器芯片,英特尔开始出货新安腾服务器处理器
  7. linux 重试密码次数超,Linux中密码策略
  8. 深圳大学算法实验一——排序算法性能分析
  9. Jquery.city-picker 实现省市区三级联动
  10. 【算力网络】算力网络的技术创新——绿色与安全关键技术