洛谷P3723 [AH2017/HNOI2017]礼物(FFT)
2024-10-16 07:55:52
首先,两个数同时增加自然数值相当于只有其中一个数增加(此增加量可以小于0)
我们令$x$为当前的增加量,${a},{b}$分别为旋转后的两个数列,那么$$ans=\sum_{i=1}^n(a_i+x-b_i)^2$$
然后把第$i$项提出来并展开,可得$$(a_i+x-b_i)^2=a_i^2+b_i^2+x^2+2xa_i-2xb_i-2a_ib_i$$
那么答案就是$$ans=\sum_{i=1}^na_i^2+\sum_{i=1}^nb_i^2+nx^2+2x(\sum_{i=1}^na_i+\sum_{i=1}^nb_i)-2\sum_{i=1}^na_ib_i$$
然后发现,答案里面只有最后一项与$a,b$的顺序有关(也就是旋转成了什么样子),前面的项都是常数(对同一个$x$来说),那么我们只要令$\sum_{i=1}^na_ib_i$最大就能让答案最小了
我们考虑一下,如果把数列$b$给反过来,那么最后一项就变成了$\sum_{i=1}^na_ib_{n-i+1}$,这是一个卷积的形式,可以直接用FFT计算1$项的系数)
那么我们把数列$b$反过来,然后把数列$a$倍长,那么两式卷积之后第$n+1$到第$2n$项里面最大值就是最大的$\sum_{i=1}^na_ib_i$
于是只要枚举一下$x$和旋转(多项式的第几项)就好了
//minamoto
#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=;const double Pi=acos(-1.0);
struct complex{
double x,y;
complex(double xx=,double yy=){x=xx,y=yy;}
inline complex operator +(complex b){return complex(x+b.x,y+b.y);}
inline complex operator -(complex b){return complex(x-b.x,y-b.y);}
inline complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[N],B[N];
int n,m,l,r[N],limit=,a[N],b[N];ll a1,a2,b1,b2,ans=inf;
void FFT(complex *A,int type){
for(int i=;i<limit;++i)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=){
complex Wn(cos(Pi/mid),type*sin(Pi/mid));
for(int R=mid<<,j=;j<limit;j+=R){
complex w(,);
for(int k=;k<mid;++k,w=w*Wn){
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y,A[j+mid+k]=x-y;
}
}
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=;i<=n;++i)
a[i]=read(),a1+=a[i]*a[i],a2+=a[i];
for(int i=;i<=n;++i)
b[i]=read(),b1+=b[i]*b[i],b2+=b[i];
for(int i=;i<=n;++i)
A[i].x=A[i+n].x=a[i],B[i].x=b[n-i+];
while(limit<=(n*)) limit<<=,++l;
for(int i=;i<limit;++i)
r[i]=(r[i>>]>>)|((i&)<<(l-));
FFT(A,),FFT(B,);
for(int i=;i<limit;++i) A[i]=A[i]*B[i];
FFT(A,-);
for(int i=;i<limit;++i) A[i].x=(ll)(A[i].x/limit+0.5);
for(int i=;i<=n;++i)
for(int j=-m;j<=m;++j)
cmin(ans,a1+b1+j*j*n+2ll*j*(a2-b2)-2ll*(ll)A[n+i].x);
printf("%lld\n",ans);
return ;
}
最新文章
- [Math] 常见的几种最优化方法
- FilterControl 显示时间并精确到时分秒的方法
- HTTP2试用小记
- 微信小程序即将开放申请?微信小论坛小程序专场16日或可见分晓
- Java 设计模式泛谈&;装饰者模式和单例模式
- LeetCode:Minimum Path Sum(网格最大路径和)
- UI1_UISlider与UISegment
- uva 757
- C#世界中的委托
- IE兼容性标签和条件注释
- mysql 时间
- .net使用RabbitMQ
- linux 下查找图片文件方法
- 《JavaScript.DOM》读书笔记
- [转帖] SS, SP, BP 三个寄存器
- [转] webpack3.0踩坑:postcss-loader的使用
- 2018.11.01 洛谷P3953 逛公园(最短路+dp)
- Kafka安装及使用
- 域控制器修改IP操作步骤
- 17、percona-toolkit
热门文章
- 在Android中使App高速、简单地支持新浪微博、微信、QQ、facebook等十几个主流社交平台的分享功能
- c# winform窗体间的传值
- 怎样解决 no jzmq in java.library.path
- contentprovider 实例
- @GetMapping和@PostMapping接收参数的格式
- xmlToEntity or entityToXML 工作笔记
- input表单元素的默认padding不一致问题
- UVA12293 Box Game —— SG博弈
- Gym - 101147E E. Jumping —— bfs
- hdu Integer Inquiry 解题报告