题目链接

描述

两个序列 \(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. sed1

    Linux sed命令 Linux 命令大全Linux sed命令是利用script来处理文本文件.sed可依照script的指令,来处理.编辑文本文件.Sed主要用来自动编辑一个或多个文件:简化对文 ...

  2. 虚拟机搭建CentOS 7系统

    准备工作先查看本机是否开启虚拟化 可以打开任务管理器中性能选项 可以看到虚拟化默认关闭,可通过打开BIOS,找到Configuration或Security选项,把Virtualization或者In ...

  3. Linxu (centos6.8)常见目录及文件解析

    /etc/sysconfig/networ-scripts/ifcfg-eth0    第一块网卡配置 BOOTPROTO="dhcp" #启用地址协议,static静态协议,bo ...

  4. Java编发编程 - 线程池的认识(一)

    每逢面试都会询问道线程池的概念和使用,但是工作中真正的又有多少场景使用呢?相信大家都会有这样的疑问:面试选拔造汽车,实际进公司就是拧螺丝!但是真正要把这颗螺丝拧紧,拧牢,没有这些最底层的知识做铺垫你可 ...

  5. vue中使用transition和animate.css动画效果

    一.单个动画中,使用div中引用animate动画 1.下载依赖 npm install animate.css –save 2.main.js中全局引用 import animate from 'a ...

  6. 微软开源的 AI 工具,让旧照片焕发新生

    原文地址:Bringing Old Photos Back to Life 原文作者:Ziyu Wan 译者 & 校正:HelloGitHub-小鱼干 & 鸭鸭 写在前面 在 GitH ...

  7. 吉他弹唱上手——使用节奏变化弹好chord谱

    本篇文章将向大家介绍如何改造来自网上的chord谱. 在各位日常的弹唱之中,应该会常常遇到朋友点歌的情况,如果点唱的这首歌我们听过,那我们尚可以靠以往的记忆来应付.如果这首歌我们只是曾经听到过听过,而 ...

  8. C语言讲义——全局变量和局部变量

    局部变量 普通的局部变量也叫动态变量,默认有个关键字叫auto,可以省略.有两种形式: 1.函数内的局部变量 2.复合语句内的局部变量:for(int i = 0; i<5; i++){-} 静 ...

  9. Java基础教程——命令行运行Java代码

    视屏讲解:https://www.bilibili.com/video/av48196406/?p=4 命令行运行Java代码 (1)使用记事本新建文本文件[Test.java]. 注意,默认状态下W ...

  10. 杂篇-之裸眼3D渲染相机及画面矫正

    主题公园类,或大型广场led屏幕,直角幕,三维影片如何制作,和最终画面如何矫正还原. 前两天,一朋友做的项目,大概就是一个柱状的led屏幕,可能是立在广场街角等处,如果这样子,那个柱状体的有颜色的两面 ...