正题
题目链接:https://www.luogu.com.cn/problem/P3723
题目大意
两个长度为nnn的序列xxx和yyy,可以旋转序列xxx之后让一个序列的所有数加上一个非负整数ccc。
要求最小化∑i=1n(xi−yi)2\sum_{i=1}^n(x_i-y_i)^2i=1∑n(xi−yi)2
解题思路
其实就是要求最小化∑i=1n(xi+c−yi)2\sum_{i=1}^n(x_i+c-y_i)^2i=1∑n(xi+c−yi)2
⇒∑i=1nxi2+∑i=1nyi2+2nc2+2∗(∑i=1nxi−∑j=1nyi)+2∗∑i=1xiyi\Rightarrow \sum_{i=1}^nx_i^2+\sum_{i=1}^ny_i^2+2nc^2+2*(\sum_{i=1}^nx_i-\sum_{j=1}^ny_i)+2*\sum_{i=1}x_iy_i⇒i=1∑nxi2+i=1∑nyi2+2nc2+2∗(i=1∑nxi−j=1∑nyi)+2∗i=1∑xiyi
式子由很多个分开的段组成,其中对于2nc2+2∗(∑i=1nxi−∑j=1nyi)2nc^2+2*(\sum_{i=1}^nx_i-\sum_{j=1}^ny_i)2nc2+2∗(∑i=1nxi−∑j=1nyi)我们可以枚举ccc来求最小值,然后考虑最小化2∗∑i=1nxiyi2*\sum_{i=1}^nx_iy_i2∗∑i=1nxiyi
对于式子∑i=1nxiyi\sum_{i=1}^nx_iy_i∑i=1nxiyi把xix_ixi翻转之后就成了∑i=1nxn−i+1yi\sum_{i=1}^nx_{n-i+1}y_i∑i=1nxn−i+1yi,是一个卷积的形式,我们再把翻转后的xxx复制一份放在后面,然后跑多项式乘法就可以发现对于乘法后的多项式fn+if_{n+i}fn+i这个位置就是将序列xxx翻转iii次之后的答案。
时间复杂度O(nlogn)O(n\log n)O(nlogn)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<complex>
#include<cmath>
#define ll long long
using namespace std;
typedef complex<double> comp;
const double Pi=acos(-1.0);
const ll N=4e5+10;
ll n,m,r[N],g[N],answer,ans,suma,sumb;
comp a[N],b[N];
void fft(comp *f,ll op){for(ll i=0;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1;comp tmp(cos(Pi/len),sin(Pi/len)*op);for(ll k=0;k<n;k+=p){comp buf(1,0);for(ll i=k;i<k+len;i++){comp tt=buf*f[i+len];f[i+len]=f[i]-tt;f[i]=f[i]+tt;buf=buf*tmp;}} }if(op==-1)for(ll i=0;i<n;i++)g[i]=(ll)(f[i].real()/n+0.5);return;
}
void Mul(){ll m;for(m=3*n,n=1;n<=m;n<<=1);for(ll i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);fft(a,1);fft(b,1);for(ll i=0;i<n;i++)a[i]=a[i]*b[i];fft(a,-1);return;
}
int main()
{scanf("%lld%lld",&n,&m);ll k=n;for(ll i=1;i<=n;i++){scanf("%lf",&a[i]);ans+=a[i].real()*a[i].real();suma+=a[i].real();}for(ll i=1;i<=n;i++){scanf("%lf",&b[i]);ans+=b[i].real()*b[i].real();sumb+=b[i].real();}for(ll i=1;i<=n/2;i++)swap(a[i],a[n-i+1]);for(ll i=1;i<=n;i++)a[i+n]=a[i];Mul();answer=1e18;for(ll i=k+1;i<=2*k;i++)for(ll j=-m;j<=m;j++)answer=min(answer,ans+k*j*j+2ll*j*(suma-sumb)-2ll*g[i]);printf("%lld",answer);
}