[AH2017/HNOI2017]礼物
2018-04-13 17:18
148 查看
题面在这里
可以在任何一个环的所有装饰物的亮度同时加上一个非负整数\(c\),
也可以将手环任意旋转,但不能翻转;
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号\(1,2,…,n\),其中\(n\)为每个手环的装饰物个数,则两个手环之间的差异值为
\[\sum_{i=1}^{n}(x_i-y_i)^2\]
进行调整(亮度改造和旋转)使得两个手环之间的差异值最小,求出这个最小值。
即我们要调整亮度使得
\[\sum_{i=1}^{n}(x_i-y_i+c)^2\]
最小(\(c\)可以为任意整数)
拆一下式子
\[\sum_{i=1}^{n}(x_i-y_i+c)^2\]
\[=\sum_{i=1}^{n}x_i^2+\sum_{i=1}^{n}y_i^2-2\sum_{i=1}^{n}x_iy_i+nc^2+2c\sum_{i=1}^{n}(x_i-y_i)\]
后面\(f(c)=nc^2+2c\sum_{i=1}^{n}(x_i-y_i)\)这个函数的系数不会受到环旋转的影响
我们设\(a=n,b=2\sum_{i=1}^{n}(x_i-y_i)\),则当\(c=-\frac{b}{2a}\)时\(f(c)\)最小
但这里\(c\)只能为整数,我的做法是求出\(c=[-\frac{b}{2a}]\),
然后对\(f(c-1),f(c),f(c+1)\)取个\(min\)
前面同样只有\(-2\sum_{i=1}^{n}x_iy_i\)会受到环旋转的影响,
我们考虑如何让\(\sum_{i=1}^{n}x_iy_i\)最大
当\(n\le 5000\)时,直接做\(n\)次即可
我们把\(y_i\)倒序处理一下,就可以得到\(\sum_{i=1}^{n}x_iy_{n-i+1}\)
这其实就是一个卷积的形式
于是我们考虑对\(x_{1...n}\)和倒序后的\(y_{n...1}\)做\(FFT\)
对于\(FFT\)的结果式\(z_{1...2n-1}\)求出\(max_{i=1}^{n}(z_i+z_{n+i})\)
即是我们要求的\(max(\sum_{i=1}^{n}x_iy_i)\)
于是这题就我们就做完了
题意
两个带有\(n\)个装饰物的手环,环上每个装饰物都有一个亮度\(x_i/y_i\),每个装饰物的初始亮度小于等于\(m\)。可以在任何一个环的所有装饰物的亮度同时加上一个非负整数\(c\),
也可以将手环任意旋转,但不能翻转;
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号\(1,2,…,n\),其中\(n\)为每个手环的装饰物个数,则两个手环之间的差异值为
\[\sum_{i=1}^{n}(x_i-y_i)^2\]
进行调整(亮度改造和旋转)使得两个手环之间的差异值最小,求出这个最小值。
数据范围
\[n\le 50000,m\le 100\]sol
70pts(\(n\le 5000\))
亮度改造的操作实际上就是在最后的表达式内部每个差值加上一个整数\(c\),即我们要调整亮度使得
\[\sum_{i=1}^{n}(x_i-y_i+c)^2\]
最小(\(c\)可以为任意整数)
拆一下式子
\[\sum_{i=1}^{n}(x_i-y_i+c)^2\]
\[=\sum_{i=1}^{n}x_i^2+\sum_{i=1}^{n}y_i^2-2\sum_{i=1}^{n}x_iy_i+nc^2+2c\sum_{i=1}^{n}(x_i-y_i)\]
后面\(f(c)=nc^2+2c\sum_{i=1}^{n}(x_i-y_i)\)这个函数的系数不会受到环旋转的影响
我们设\(a=n,b=2\sum_{i=1}^{n}(x_i-y_i)\),则当\(c=-\frac{b}{2a}\)时\(f(c)\)最小
但这里\(c\)只能为整数,我的做法是求出\(c=[-\frac{b}{2a}]\),
然后对\(f(c-1),f(c),f(c+1)\)取个\(min\)
前面同样只有\(-2\sum_{i=1}^{n}x_iy_i\)会受到环旋转的影响,
我们考虑如何让\(\sum_{i=1}^{n}x_iy_i\)最大
当\(n\le 5000\)时,直接做\(n\)次即可
100pts (\(n\le 500000\))
考虑\(\sum_{i=1}^{n}x_iy_i\)这个式子我们把\(y_i\)倒序处理一下,就可以得到\(\sum_{i=1}^{n}x_iy_{n-i+1}\)
这其实就是一个卷积的形式
于是我们考虑对\(x_{1...n}\)和倒序后的\(y_{n...1}\)做\(FFT\)
对于\(FFT\)的结果式\(z_{1...2n-1}\)求出\(max_{i=1}^{n}(z_i+z_{n+i})\)
即是我们要求的\(max(\sum_{i=1}^{n}x_iy_i)\)
于是这题就我们就做完了
代码
#include<bits/stdc++.h> #include<algorithm> #include<iostream> #include<cstdlib> #include<iomanip> #include<cstring> #include<complex> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define mp make_pair #define pub push_back #define puf push_front #define pob pop_back #define pof pop_front #define RG register #define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const dd eps=1e-10; const dd pi=acos(-1); const int N=1000000; const int inf=1e9+7; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar(); return data*w; } struct point{dd r,i;}A ,B ; point operator +(point x,point y) {return (point){x.r+y.r,x.i+y.i};} point operator -(point x,point y) {return (point){x.r-y.r,x.i-y.i};} point operator *(point x,point y) {return (point){x.r*y.r-x.i*y.i,x.i*y.r+y.i*x.r};} int n,m,l,a ,b ,r ,ans,ret,sum,sumx,c; il void fft(point *A,int n,int opt){ for(RG int i=0;i<n;i++)if(i<r[i])swap(A[i],A[r[i]]); for(RG int i=2;i<=n;i<<=1){ RG point w=(point){cos(2*pi/i),opt*sin(2*pi/i)}; for(RG int j=0;j<n;j+=i){ RG point wn=(point){1,0}; for(RG int k=j;k<j+(i>>1);k++,wn=wn*w){ RG point x=wn*A[k+(i>>1)]; A[k+(i>>1)]=A[k]-x; A[k]=A[k]+x; } } } } int main() { n=read();m=read(); for(RG int i=0;i<n;i++) A[i].r=a[i]=read(),ans+=a[i]*a[i],sumx+=a[i]; for(RG int i=n-1;~i;i--) B[i].r=b[i]=read(),ans+=b[i]*b[i],sumx-=b[i]; for(m=n-1,n=1;n<=m+m;n<<=1,l++); for(RG int i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((1&i)<<(l-1)); fft(A,n,1);fft(B,n,1); for(RG int i=0;i<n;i++)A[i]=A[i]*B[i]; fft(A,n,-1); for(RG int i=0;i<n;i++)a[i]=int(A[i].r/n+0.5); for(RG int i=0;i<m;i++)ret=max(ret,2*(a[i]+a[i+m+1])); ret=max(ret,2*a[m]);n=m+1; c=-sumx/n;c=min(n*c*c+2*sumx*c,n*(c-1)*(c-1)+2*sumx*(c-1)); c=min(c,n*(-sumx/n+1)*(-sumx/n+1)+2*sumx*(-sumx/n+1)); printf("%d\n",ans-ret+c); return 0; }
相关文章推荐
- [AH2017/HNOI2017]礼物
- 洛谷3723 [AH2017/HNOI2017]礼物
- luogu3723 [AH2017/HNOI2017]礼物 【NTT】
- BZOJ4827:[AH2017/HNOI2017]礼物——题解
- 给c++程序员的一份礼物——常用工具集
- 新年新礼物
- 天使的礼物
- Google对合作站点送礼物,居然是Google牌冰箱
- 送给程序员的节日礼物!
- 麦琪的礼物
- 51CTO两周岁生日礼物﹕三千万人次访问量 推荐
- 新年到了,祝大家新年快乐,礼物就送SSD1的部分答案哦
- 《兰岛物语:少女的约定》全后宫攻略补遗还有永恒的礼物简介和秘籍
- 收到的礼物——微软蓝牙无线鼠标5000
- [礼物]发布一款silverlight开发的相册
- 送给未来孩子的礼物
- 给软件技术学习者的礼物——《WCF概述》教学PPT及相关示例
- 一起来HAPPY,不得不送的礼物哦!
- 谁在圣诞节送礼物?
- 现身说法,如何给上司送礼物