版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/84146401
传送门
入门题。
考虑展开要求的式子
=>
令
=>
化到这一步的时候我卡了一下。
考虑第一坨可以直接算,第二坨可以取二次函数对称轴附近求极值。
关键在于第三坨的极值。
这个怎么求呢?
考虑将
数组翻转。
这样对
进行
,然后得到的新数列
中的
就对应着数列
的一种对齐方法的和。
因此只需要在
之后给
取个
就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
const int mod=998244353,N=2e5+5;
int n,m,a[N],b[N],pos[N],ans=0,lim=1,tim=0,mx=0,sum=0;
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=(ll)a*a%mod)if(p&1)ret=(ll)ret*a%mod;return ret;}
inline void ntt(int a[],int type){
for(int i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
int mult=(mod-1)>>1,typ=type==1?3:(mod+1)/3;
for(int wn,mid=1;mid<lim;mid<<=1,mult>>=1){
wn=ksm(typ,mult);
for(int len=mid<<1,j=0;j<lim;j+=len){
int w=1;
for(int k=0;k<mid;++k,w=(ll)w*wn%mod){
int a0=a[j+k],a1=(ll)a[j+k+mid]*w%mod;
a[j+k]=(a0+a1)%mod,a[j+k+mid]=(a0-a1+mod)%mod;
}
}
}
}
inline int calc(int x){return (n+1)*x*x-2*sum*x;}
int main(){
freopen("lx.in","r",stdin);
n=read()-1,m=read();
for(int i=0;i<=n;++i)a[i]=read(),ans+=a[i]*a[i],sum+=a[i];
for(int i=n;~i;--i)b[i]=read(),ans+=b[i]*b[i],sum-=b[i];
while(lim<=n*2)lim<<=1,++tim;
int p=sum/(n+1);
ans+=min(min(calc(p-1),calc(p)),calc(p+1));
for(int i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
ntt(a,1),ntt(b,1);
for(int i=0;i<lim;++i)a[i]=(ll)a[i]*b[i]%mod;
ntt(a,-1);
int inv=ksm(lim,mod-2);
for(int i=0;i<=n*2;++i)a[i]=(ll)a[i]*inv%mod;
for(int i=0;i<=n;++i)mx=max(mx,a[i]+a[i+n+1]);
cout<<ans-2*mx;
return 0;
}