【GDSOI2017第三轮模拟】Gift
2017-04-19 21:25
295 查看
Description
n<=50000
Solution
刚刚考完体育中考,整个人都颓废了_ (:з」∠) _于是决定写一个FFT冷静一下~
我们可以强制把加的数都放到y上面,这样c的非负整数限制也没有了。
那么我们把式子化一下:
∑i=1n(xi−(yi+c))2=∑i=1nx2i+∑i=1n(yi+c)2−2∑i=1nxi(yi+c)
=∑i=1nx2i+∑i=1ny2i+nc2+2c∑i=1n(yi−xi)−2∑i=1nxiyi
发现前两项为定值,扔掉。
把和c有关的项提出来,发现是一个形如ac^2+bc的二次函数,要求最小值。
这样就可以把c求出来了,也就是我们只需要求旋转过后的∑ni=1xiyi的最大值。
考虑FFT,把y翻转,那么就是形如∑ni=1xiyn−i+1,也就是卷积的形式。
将x串倍长,那么对于每一个x串的结尾,往前长度为n的串和y串的卷积就是这一段串的答案。
于是直接上FFT,最后对每个答案求个最大值就好了。
听说循环卷积跑得快?我不会啊QwQ
Code
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define pi acos(-1) using namespace std; typedef double db; const int N=4*1e5+5; struct complex{ db r,i; complex(db _r=0,db _i=0) {r=_r;i=_i;} friend complex operator + (complex x,complex y) {return complex(x.r+y.r,x.i+y.i);} friend complex operator - (complex x,complex y) {return complex(x.r-y.r,x.i-y.i);} friend complex operator * (complex x,complex y) {return complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);} }A ,B ,C ,t ; int n,m,ans,sumx,sumy,len,lg; db x ,y ,z ; void DFT(complex *a,int flag) { for(int i=0;i<len;i++) { int p=0; for(int j=i,k=0;k<lg;k++,j/=2) p=p*2+(j&1); t[p]=a[i]; } for(int m=2;m<=len;m*=2) { int half=m/2; for(int i=0;i<half;i++) { complex w=complex(cos(i*flag*pi/half),sin(i*flag*pi/half)); for(int j=i;j<len;j+=m) { complex u=t[j],v=t[j+half]*w; t[j]=u+v;t[j+half]=u-v; } } } for(int i=0;i<len;i++) a[i]=t[i]; if (flag==-1) for(int i=0;i<len;i++) a[i].r/=len; } void FFT(db *a,db *b,db *c) { for(int i=0;i<len;i++) { A[i]=complex(a[i],0); B[i]=complex(b[i],0); } DFT(A,1);DFT(B,1); for(int i=0;i<len;i++) C[i]=A[i]*B[i]; DFT(C,-1); for(int i=0;i<len;i++) c[i]=C[i].r; } int main() { freopen("gift.in","r",stdin); freopen("gift.out","w",stdout); scanf("%d%d",&n,&m); fo(i,0,n-1) scanf("%lf",&x[i]),sumx+=x[i],ans+=x[i]*x[i]; fo(i,0,n-1) scanf("%lf",&y[i]),sumy+=y[i],ans+=y[i]*y[i]; db a=n,b=2*(sumy-sumx); db c=-b/2.0/a; int c1=floor(c),c2=ceil(c); if (c-c1<c2-c) c=c1;else c=c2; ans+=a*c*c+b*c; fo(i,n,2*n-1) x[i]=x[i-n]; fo(i,1,n/2) swap(y[i-1],y[n-i]); int nn=n,sum=0;n*=2; for(len=1;len<2*n;len*=2) lg++; FFT(x,y,z); fo(i,nn,n-1) sum=max(sum,(int)z[i]); printf("%d\n",ans-2*sum); }
相关文章推荐
- [JZOJ5083].【GDSOI2017第三轮模拟】Gift
- 【jzoj5083】【GDSOI2017第三轮模拟】【Gift】【快速傅立叶变换】
- 【GDSOI2017第三轮模拟】Travel Plan(DP)
- [JZOJ5082].【GDSOI2017第三轮模拟】Informatics Training
- 【jzoj5081】【GDSOI2017第三轮模拟】【Travel Plan】【动态规划】
- 【GDSOI2017第三轮模拟】Informatics Training(码农,平衡树)
- [JZOJ5081]. 【GDSOI2017第三轮模拟】Travel Plan
- 【JZOJ5081】【GDSOI2017第三轮模拟】Travel Plan
- 【GDSOI2017第三轮模拟】Travel Plan 背包
- 【JZOJ5082】【GDSOI2017第三轮模拟】Informatics Training
- 【GDSOI2017第三轮模拟】Travel Plan
- [JZOJ5078].[AC自动机复习]【GDOI2017第三轮模拟day2】魔法咒语
- CodeForcess--609B--The Best Gift(模拟水题)
- 【GDSOI2017模拟4.13】炮塔 最小割
- bzoj5139 [Usaco2017 Dec]Greedy Gift Takers(二分答案+模拟)
- 【JZOJ5056】【GDSOI2017模拟4.13】黑白广场
- 【jzoj5094】【GDSOI2017第四轮模拟day3】【鸽子】【计算几何】
- 【JZOJ5057】【GDSOI2017模拟4.13】炮塔
- 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔
- 【GDSOI2017第二轮模拟】树