Problem

Description

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

但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的整数 \(c\)(可能是负数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。

在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 \(1, 2,\cdots, n\),其中 \(n\) 为每个手环的装饰物个数,第一个手环的 \(i\) 号位置装饰物亮度为 \(x_i\),第二个手环的 \(i\) 号位置装饰物亮度为 \(y_i\),两个手环之间的差异值为(参见输入输出样例和样例解释):

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

麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?

Input Format

输入数据的第一行有两个数 \(n, m\),代表每条手环的装饰物的数量为 \(n\),每个装饰物的初始亮度小于等于 \(m\);

接下来两行,每行各有 \(n\) 个数,分别代表第一条手环和第二条手环上从某个位置开始逆时针方向上各装饰物的亮度。

Output Format

输出一个数,表示两个手环能产生的最小差异值。注意在将手环改造之后,装饰物的亮度可以大于 \(m\)。

Sample

Input

5 6
1 2 3 4 5
6 3 3 4 5

Output

1

Explanation

Explanation for Sample

需要将第一个手环的亮度增加 \(1\),第一个手环的亮度变为:\(2, 3, 4, 5, 6\)。旋转一下第二个手环,对于该样例,是将第二个手环的亮度 \(6, 3, 3, 4, 5\) 向左循环移动一个位置,使得第二手环的最终的亮度为:\(3, 3, 4, 5, 6\)。

此时两个手环的亮度差异值为 \(1\)。

Range

对于 \(30\%\) 的数据,\(n\le 500, m\le 10\);

对于 \(70\%\) 的数据,\(n\le 5000\);

对于 \(100\%\) 的数据,\(1\le n\le 50000, 1\le m\le 100, 1\le a_i\le m\)。

Algorithm

多项式

Mentality

由于加上的整数可以为负数,那么无论加在 \(x\) 还是 \(y\) 上没有本质差别。直接加在 \(x\) 上就好了。

那么对于式子:

\[\sum (x_i+c-y_i)^2
\]

我们可以拆开平方:

\[=\sum x_i^2+y_i^2+c^2+2x_ic-2y_ic-2x_iy_i\\
=\sum x_i^2+\sum y_i^2+nc^2+2(\sum x_i-\sum y_i)c-2\sum x_iy_i
\]

好的,前面两项都是定值。对于带 \(c\) 的项,由于其他系数皆为定值,就是一个普通的二次函数,直接找顶点即可最小。

那么我们只需要令 \(\sum x_iy_i\) 最大即可。考虑将 \(x\) 数组的下标翻转,则得到 \(\sum x_{n-i+1}*y_i\) 。

那么将 \(x\) 数组复制加倍,直接 \(FFT\) 将 \(x,y\) 乘起来,第 \(n+1\sim 2n\) 项就是 \(n\) 种旋转方法的结果,直接取 \(max\) 即可。

Code

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
long long read() {
long long x = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) w = ch == '-' ? -1 : 1, ch = getchar();
while (isdigit(ch)) {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
return x * w;
}
#define cp complex<double>
const int Max_n = 5e5 + 5;
const double pi = acos(-1);
int n, m, ans;
int sx, sy, Max, mid, x[Max_n], y[Max_n];
int lim = 1, bit, rev[Max_n];
cp f[Max_n], g[Max_n];
void dft(cp *f, int t) {
for (int i = 0; i < lim; i++)
if (rev[i] > i) swap(f[i], f[rev[i]]);
for (int len = 1; len < lim; len <<= 1) {
cp Wn(cos(t * pi / len), sin(t * pi / len));
for (int i = 0; i < lim; i += len << 1) {
cp Wnk(1, 0);
for (int k = i; k < i + len; k++) {
cp a = f[k], b = Wnk * f[k + len];
f[k] = a + b, f[k + len] = a - b;
Wnk *= Wn;
}
}
}
}
void FFT() {
dft(f, 1), dft(g, 1);
for (int i = 0; i < lim; i++) f[i] *= g[i];
dft(f, -1);
for (int i = 0; i < lim; i++) f[i] /= lim;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("3723.in", "r", stdin);
freopen("3723.out", "w", stdout);
#endif
n = read(), m = read();
for (int i = 0; i < n; i++) {
f[i] = x[i] = read();
sx += x[i], ans += x[i] * x[i];
}
for (int i = 0; i < n; i++) {
g[i] = y[i] = read();
sy += y[i], ans += y[i] * y[i];
}
reverse(f, f + n);
for (int i = 0; i < n; i++) f[i + n] = f[i];
while (lim <= n * 3) bit++, lim <<= 1;
for (int i = 0; i < lim; i++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
FFT();
for (int i = n; i < 2 * n; i++) Max = max(Max, (int)(f[i].real() + 0.5));
double tp = double(sy - sx) / n;
mid = (int)(tp += tp < 0 ? -0.5 : 0.5);
cout << (ans += n * mid * mid + 2 * (sx - sy) * mid - 2 * Max);
}

【HNOI 2017】礼物的更多相关文章

  1. [HNOI 2017]礼物

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

  2. AH/HNOI 2017 礼物

    题目链接 描述 两个序列 \(x, y\),可以将一个序列每个值同时加非负整数 \(c\),其中一个序列可以循环移位,要求最小化: \[\sum_{i = 1}^{n}(x_i - y_i) ^ 2 ...

  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. java8-StreamAPI之collection归约操作

    一说明 经过前一篇的StreamAPI学习,基本的流操作我相信大家都熟练于心了,那么今天是要详细解析一下收集器(collect)这么API 前提要区分,collect(StreamAPI)与coll ...

  2. Python面向对象-概念、类、实例

    OOP——Object Oriented Programming,面向对象编程,是一种程序设计思想.该思想将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 区别于面向过程的程序设计即把计 ...

  3. Python活力练习Day2

    Day2:求1000以内的素数 #素数:除了1和它本身外,不能被其他自然数整除 #判断素数的方法:1).暴力法:从2到n-1每个数均整除进行判断   2).开根号法:从2到sqrt(n)均做整除判断( ...

  4. PMBOK 指南 第三章 项目经理的角色

    项目经理的角色 3.1 概述 项目经理类似于交响乐团的指挥 成员与角色 在团队中的职责 知识和技能:具备项目管理知识.技术知识.理解和经验. 3.2 定义 项目经理是由执行组织委派,领导团队实现项目目 ...

  5. Beta版本演示

    小组信息 组名:斗地组 组长博客:地址 组内成员: 组员 学号 林涛(组长) 031702616 童圣滔 031702117 林红莲 031702213 潘雨佳 031702214 覃鸿浩 03170 ...

  6. LINUX OS 正常关机失败

    描述:LINUX OS运行命令shutdown now显示:Telling INIT to go to single user mode....   解决方法:运行命令exit重新登录,再运行 hal ...

  7. TCPUDPDbg(TCP UDP 网络调试工具)

    下载链接:https://pan.baidu.com/s/1oan44qop73X5VuBcE-rjeA  提取码:v0oa

  8. C语言程序设计100例之(25):确定进制

    例25    确定进制 问题描述 6*9 = 42 对于十进制来说是错误的,但是对于13进制来说是正确的.即 6(13)* 9(13)= 42(13),因为,在十三进制中,42 = 4 * 13 + ...

  9. C语言笔记 02_基本语法&数据类型&变量

    基本语法 令牌 C 程序由各种令牌组成,令牌可以是关键字.标识符.常量.字符串值,或者是一个符号.例如,下面的 C 语句包括五个令牌: printf("Hello, World! \n&qu ...

  10. Python——面向对象(类)的基础疑难点

    相信用Python写def函数大家都信手拈来了,但Python作为面向对象的编程语言,怎么能浪费呢? 那问题来了.什么是类呢?什么是实例?什么是对象?方法是什么??属性又是什么???继承?封装?多态? ...