【刷题】BZOJ 4827 [Hnoi2017]礼物
Description
我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n,其中 n 为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手 环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释): \sum_{i=1}{n}(x_i-y_i)2麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?
Input
输入数据的第一行有两个数n, m,代表每条手环的装饰物的数量为n,每个装饰物的初始 亮度小于等于m。
接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时 针方向上各装饰物的亮度。
1≤n≤50000, 1≤m≤100, 1≤ai≤m
Output
输出一个数,表示两个手环能产生的最小差异值。
注意在将手环改造之后,装饰物的亮度 可以大于 m。
Sample Input
5 6
1 2 3 4 5
6 3 3 4 5
Sample Output
1
【样例解释】
需要将第一个手环的亮度增加1,第一个手环的亮度变为: 2 3 4 5 6 旋转一下第二个手环。对于该样例,是将第
二个手环的亮度6 3 3 4 5向左循环移动 2017-04-15 第 6 页,共 6 页 一个位置,使得第二手环的最终的亮度为
:3 3 4 5 6。 此时两个手环的亮度差异值为1。
Solution
可以变换位置,也可以同时加数
假设确定了两个序列的位置,那么答案就是 \(\sum_{i=0}^{n-1}(xi-yi+c)^2\)
拆开, \(\sum_{i=0}^{n-1}x_i^2+y_i^2+c^2-2x_iy_i+2x_ic-2y_ic\)
\(~~~~(\sum_{i=0}^{n-1}x_i^2+y_i^2)+(\sum_{i=0}^{n-1}c^2+2c(x_i-y_i))-2(\sum_{i=0}^{n-1}x_iy_i)\)
\(=[(\sum_{i=0}^{n-1}x_i^2)+(\sum_{i=0}^{n-1}y_i^2)]+[nc^2+2((\sum_{i=0}^{n-1}x_i)-(\sum_{i=0}^{n-1}y_i))c]-2[\sum_{i=0}^{n-1}x_iy_i]\)
然后,第一部分就是求和,第二部分可以发现是个系数确定的二次函数,要最小肯定是取最值
也就是说,对于每一种不同的序列的排列,有两项的值是一直不变的。那么我们只要算第三部分,找排列使第三部分的值最小,那么就会使最终答案最小
其实把 \(y\) 数组翻转一下,就会发现它其实就是个FFT
假设两个数组是这样对应的

那么 \(y\) 数组翻转之后变成了这样

变成了两个交叉部分,而这两个部分对应的形式不就是FFT的形式吗
于是就枚举两个部分的分界点,将两个FFT加起来就是一种对应方案的第三部分的答案
对所有方案取min就好了
注意的一点是,在求二次函数的最值的时候,因为数列同时加数必须是自然数,小数不行,那么就不能直接用最值公式去得到最值,必须得到两个最接近对称轴的整数点,用它们求函数值取min
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=1<<17,inf=0x3f3f3f3f;
const db Pi=acos(-1.0);
int qn,n,m,rev[MAXN],G[MAXN],ans=inf,xs,ys,xs2,ys2,cnt,x1,x2,ext;
struct Complex{
db real,imag;
inline Complex operator + (const Complex &A) const {
return (Complex){real+A.real,imag+A.imag};
};
inline Complex operator - (const Complex &A) const {
return (Complex){real-A.real,imag-A.imag};
};
inline Complex operator * (const Complex &A) const {
return (Complex){real*A.real-imag*A.imag,imag*A.real+real*A.imag};
};
};
Complex x[MAXN],y[MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void FFT(Complex *A,int tp)
{
for(register int i=0;i<n;++i)
if(i<rev[i])std::swap(A[i],A[rev[i]]);
for(register int l=2;l<=n;l<<=1)
{
Complex wn=(Complex){cos(2*Pi/l),sin(tp*2*Pi/l)};
for(register int i=0;i<n;i+=l)
{
Complex w=(Complex){1,0};
for(register int j=0;j<(l>>1);++j)
{
Complex A1=A[i+j],A2=A[i+j+(l>>1)]*w;
A[i+j]=A1+A2,A[i+j+(l>>1)]=A1-A2;
w=w*wn;
}
}
}
}
int main()
{
read(qn);read(m);
for(register int i=0;i<qn;++i)
{
int k;read(k);
x[i].real=(db)k,xs+=k,xs2+=k*k;
}
for(register int i=0;i<qn;++i)
{
int k;read(k);
y[qn-i-1].real=(db)k,ys+=k,ys2+=k*k;
}
m=qn+qn-1;
for(n=1;n<m;n<<=1)cnt++;
for(register int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
FFT(x,1);FFT(y,1);
for(register int i=0;i<n;++i)x[i]=x[i]*y[i];
FFT(x,-1);
for(register int i=0;i<n;++i)G[i]=(int)(x[i].real/n+0.5);
chkmin(ans,-2*G[qn-1]);
for(register int i=0;i<qn;++i)chkmin(ans,-2*(G[i]+G[i+qn]));
x1=ceil((db)-(xs-ys)/qn),x2=floor((db)-(xs-ys)/qn);
ext=min(qn*x1*x1+2*(xs-ys)*x1,qn*x2*x2+2*(xs-ys)*x2);
write(ans+xs2+ys2+ext,'\n');
return 0;
}
【刷题】BZOJ 4827 [Hnoi2017]礼物的更多相关文章
- bzoj 4827: [Hnoi2017]礼物 [fft]
4827: [Hnoi2017]礼物 题意:略 以前做的了 化一化式子就是一个卷积和一些常数项 我记着确定调整值还要求一下导... #include <iostream> #include ...
- bzoj 4827 [Hnoi2017]礼物——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4827 式子就是 \sum_{i=0}^{n-1}(a[ i ] - b[ i+k ] + c ...
- bzoj 4827 [Hnoi2017] 礼物 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4827 首先,旋转对应,可以把 b 序列扩展成2倍,则 a 序列对应到的还是一段区间: 再把 ...
- bzoj 4827: [Hnoi2017]礼物【FFT】
记得FFT要开大数组!!开到快MLE的那种!!我这个就是例子TAT,5e5都RE了 在这题上花的时间太多了,还是FFT不太熟练. 首先看70分的n方做法:从0下标开始存,先n--,把a数组倍增,然后枚 ...
- bzoj 4827: [HNOI2017]礼物 (FFT)
一道FFT 然而据说暴力可以水70分 然而我省选的时候看到了直接吓傻了 连暴力都没打 太弱了啊QAQ emmmm 详细的拆开就看其他题解吧233 最后那一步卷积其实我一直没明白 后来画画图终于懂了 ...
- BZOJ:4827: [Hnoi2017]礼物
[问题描述] 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度. 但是在她生日的 ...
- BZOJ 4827 [Hnoi2017]礼物 ——FFT
题目上要求一个循环卷积的最小值,直接破环成链然后FFT就可以了. 然后考虑计算的式子,可以分成两个部分分开计算. 前半部分FFT,后半部分扫一遍. #include <map> #incl ...
- BZOJ 4827: [Hnoi2017]礼物 FFT_多项式_卷积
题解稍后在笔记本中更新 Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r&q ...
- 4827: [Hnoi2017]礼物
4827: [Hnoi2017]礼物 链接 分析: 求最小的$\sum_{i=1}^{n}(x_i-y_i)^2$ 设旋转了j位,每一位加上了c. $\sum\limits_{i=1}^{n}(x_{ ...
随机推荐
- 【NAS】CIFS用户场景需求分析
1.everyone用户 1.1: 场景描述:共享目录为rule,所有用户都可以查看,但是不能修改: 解决方法:在smb.conf里配置read only = yes,具体示例如下: [rule] p ...
- spl_autoload_register()函数
一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.class.php <?php class PRINTI ...
- Andorid自定义attr的各种坑
本文来自网易云社区 作者:孙有军 在开发Andorid应用程序中,经常会自定义View来实现各种各样炫酷的效果,在实现这吊炸天效果的同时,我们往往会定义很多attr属性,这样就可以在XML中配置我们想 ...
- Spark性能优化--开发调优与资源调优
参考: https://tech.meituan.com/spark-tuning-basic.html https://zhuanlan.zhihu.com/p/22024169 一.开发调优 1. ...
- java中的比较:instanceof、equals(hashcode)、==
import javassist.expr.Instanceof; class Person{ String s; Person(String s){ this.s=s; } } class Man ...
- Java基础知识总结一
1.何为编程? 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程. 为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路.方法.和手段通过计算机能够理解 ...
- 凸包算法(Graham扫描法)详解
先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明 p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...
- 查找当前对象中的方法对象的属性叫做_event_name的方法
setattr( self, '_events', {e._event_name: e for _, e in getmembers(self, lambda x: ismethod(x) and h ...
- javaScript中两个等于号和三个等于号之间的区别
一言以蔽之:==先转换类型再比较,===先判断类型,如果不是同一类型直接为false. ===表示恒等于,比较的两边要绝对的相同 alert(0 == ""); // trueal ...
- C Program进阶-二维数组动态内存开辟
对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...