题目链接

描述

两个序列 \(x, y\),可以将一个序列每个值同时加非负整数 \(c\),其中一个序列可以循环移位,要求最小化:

\[\sum_{i = 1}^{n}(x_i - y_i) ^ 2
\]

题解

循环移位 \(\Leftrightarrow\) 断环成链。显然那个序列循环移位不影响,而且强制加值在 \(x\) 上, \(c\) 可以为负整数(可以理解为如果是负数,则把这个的绝对值加到 \(y\) 上,差保持不变),不妨让 y 移位,将 y 数组复制一倍到末尾,由于循环移位,所以 \(\sum_{i=1}^{n} y_{j + i} = \sum_{i=1}^{n} y_i\)。

\[ans = \min\{ \sum_{i = 1}^{n} (x_i + c - y_{j + i}) ^ 2 \}
\]

把里面这个东西拿出来:

\[\sum_{i = 1}^{n} (x_i + c - y_{j + i}) ^ 2 = \sum_{i=1}^{n}x_i ^ 2 + \sum_{i=1}^{n}y_i^2 + nc^2 + 2c\sum(x_i - y_i) - 2 \sum x_i y_{i + j}
\]

要让这个式子尽量小:

  • 前两项是定值
  • 第 \(3, 4\) 项是一个关于 \(c\) 的开口向上二次函数,由于要求取整数,所以算对称轴,算一下最近的两个整数取最优值即可。

比较棘手的是最后一项 \(\sum x_i y_{i + j}\) (可以忽略系数),感觉可以转化成卷积的形式,用套路性的反转序列试试看:

新建一个数组 \(z\),令 \(z_{2n - i + 1} = y_i\)

\(\sum x_i y_{i + j} = \sum x_i z_{2n + 1 - i - j}\),很显然的一个卷积,即从 \(j\) 位开始的答案记录在了 \(2n - j + 1\) 位的系数上。

Tips

  • C++ 如果是负数整除会上取整,注意特判

时间复杂度

\(O(Nlog_2N)\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL; const int N = 2e5 + 5;
const double PI = acos(-1); int n, m, c, lim = 1, len, rev[N], x[N], y[N];
LL ans = 0; struct CP{
double x, y;
CP operator + (const CP &b) const { return (CP){ x + b.x, y + b.y }; }
CP operator - (const CP &b) const { return (CP){ x - b.x, y - b.y }; }
CP operator * (const CP &b) const { return (CP){ x * b.x - y * b.y, x * b.y + y * b.x }; }
} F[N], G[N]; void FFT(CP a[], int opt) {
for (int i = 0; i < lim; i++) if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int m = 1; m <= lim; m <<= 1) {
CP wn = (CP){ cos(2 * PI / m), opt * sin(2 * PI / m) };
for (int i = 0; i < lim; i += m) {
CP w = (CP){ 1, 0 };
for (int j = 0; j < (m >> 1); j++) {
CP u = a[i + j], t = w * a[i + j + (m >> 1)];
a[i + j] = u + t, a[i + j + (m >> 1)] = u - t;
w = w * wn;
}
}
}
} int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", x + i), ans += x[i] * x[i], c += x[i];
for (int i = 1; i <= n; i++) scanf("%d", y + i), y[i + n] = y[i], ans += y[i] * y[i], c -= y[i];
// x = l 是对称轴
int l = -c / n;
if (c > 0) l--;
ans += min(l * l * n + 2 * l * c, (l + 1) * (l + 1) * n + 2 * (l + 1) * c);
LL v = 0;
for (int i = 1; i <= n; i++) F[i].x = x[i];
for (int i = 1; i <= 2 * n; i++) G[i].x = y[2 * n - i + 1];
while (lim <= 2 * n) lim <<= 1, ++len;
for (int i = 0; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
FFT(F, 1); FFT(G, 1);
for (int i = 0; i < lim; i++) F[i] = F[i] * G[i];
FFT(F, -1);
for (int i = n + 1; i <= 2 * n; i++) v = max(v, (LL)(F[i].x / lim + 0.5));
printf("%lld\n", ans - 2 * v);
return 0;
}

AH/HNOI 2017 礼物的更多相关文章

  1. [HNOI 2017]礼物

    Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...

  2. 【HNOI 2017】礼物

    Problem Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 \(n\) 个装饰物,并且每个装饰物 ...

  3. [HNOI 2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...

  4. [HNOI 2017]抛硬币

    Description 题库链接 两人抛硬币一人 \(a\) 次,一人 \(b\) 次.记正面朝上多的为胜.问抛出 \(a\) 次的人胜出的方案数. \(1\le a,b\le 10^{15},b\l ...

  5. [HNOI 2017]影魔

    Description 题库链接 给你一段长度为 \(n\) 的序列 \(K\) . \(m\) 组询问,每次给定左右端点 \(l,r\) .求出满足区间内下述贡献和. 如果一个区间的两个端点是这一个 ...

  6. 【HNOI 2017】大佬

    Problem Description 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语.你作为一个 OIer, ...

  7. 【HNOI 2017】影魔

    Problem Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还 ...

  8. HNOI 2017

    题目链接 我还是按bzoj AC数量排序做的 4827 这个其实如果推一下(求每个值)式子会发现是个卷积,然后FFT就好了 4826 记不太清了,可以求出每个点左右第一个比他的的点的位置,将点对看成平 ...

  9. [HNOI 2017]大佬

    Description 题库链接 题意简述来自Gypsophila. 你现在要怼 \(m\) 个大佬,第 \(i\) 个大佬的自信值是 \(C_i\) .每次怼大佬之前,你的自信值是 \(mc\),等 ...

随机推荐

  1. Flink Native Kubernetes实战

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. Android studio设置参数文档提示

    方法/步骤     进行点击Android studio菜单中的file的选项菜单.   弹出了下拉菜单中进行选择为"settings"的选项的菜单即可.   进入到了settin ...

  3. Python_教程_使用Visual Studio Code开发Django项目

    如何获得 Visual Studio Code 访问 http://code.visualstudio.com 下载并安装. 前提条件 安装Python 2.7 及 Python 3.5,Window ...

  4. 「NOIP2009」最优贸易 题解

    「NOIP2009」最优贸易 题解 题目TP门 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 ...

  5. git 最新笔记,工作中的必会技能

    1.状态查看: git status 可以查看工作区,暂存区的状态 untracked 在暂存区没有该文件 modified 修改过 staged 使用git add 暂存过 2.添加操作: git ...

  6. 如何用CorelDRAW画箭头?

    CorelDRAW,简称为cdr,是一款专业的矢量绘图软件,在设计界也是常用的专业设计之一,在日常的设计工作中,我们常常需要绘制一些特殊的图形,比如箭头.很多对cdr不是特别熟练的小伙伴不知道如何用c ...

  7. Vegas教程分享,制作古装墨迹笔刷开场效果

    许多酷炫的古装大片,片头曲介绍人物的时候,都有一种墨迹笔刷的开场效果,那么这个特效如何利用Vegas去做呢? 1.导入素材文件 首先呢,导入相关文件素材到视频制作软件Vegas中,点击页面上方如图1箭 ...

  8. 人人都能学会系列之ThreadLocal

    1.概览 本文我们来看下java.lang包中的ThreadLocal,它赋予我们给每个线程存储自己数据的能力. 2.ThreadLocal API ThreadLocal允许我们存储的数据只能被特定 ...

  9. Java中CLASS_PATH与注释的使用

    一.CLASS_PATH的使用 我们在安装jdk的时候,通常情况下只是在电脑的环境变量中新建一个系统变量JAVA_HOME,这个变量用于储存jdk的/bin文件夹之前路径,然后在path中使用这个系统 ...

  10. D - Number of Multisets 题解(思维dp)

    题目链接 题目大意 给你一个数k和n,表示用n个\(1/2^i(i=0,1,2.....)\)组成k有多少种方案数 题目思路 这个dp实属巧妙 设\(dp[i][j]表示i个数构成j\) 这i个数可以 ...