【题解】[AH2017/HNOI2017]礼物

Problem

设旋转好后我们加的值是\(c.\)

\[\sum_{i=0}^n (a_i-b_i+c)^2 \]

\[=\sum a_i^2+b_i^2+c^2-2a_ib_i+2a_ic-2b_ic \]

这个式子除了\(\sum -2a_ib_i\)都是定值。考虑求这个东西的最大值。

\(-2\)扔了,原式:

\[\sum a_ib_i \]

反转\(a\)得到:

\[\sum a_{n-i+1}b_i \]

这玩意是个卷积。

于是把\(a\)反转后倍长并与\(b\)进行卷积,取\(i\in \left\{n+1,n+2...\right\}[x^i]F(x)\)的最大值即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
const int N=310000;
inline int add(int x,int y){return (x+y)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1)res=mul(res,a);
		a=mul(a,a);b>>=1;
	}
	return res;
}
int n,rev[N],a[N],b[N],c[N],f[N],m;
void NTT(int *a,int lim,int tp){
	for(int i=0;i<lim;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
	for(int i=1;i<lim;i<<=1){
		int gn=qpow(3,(mod-1)/(i<<1));
		if(tp==-1)gn=qpow(gn,mod-2);
		for(int j=0;j<lim;j+=(i<<1)){
			int G=1;
			for(int k=0;k<i;++k,G=mul(G,gn)){
				int x=a[j+k],y=mul(G,a[i+j+k]);
				a[j+k]=add(x,y);a[i+j+k]=add(x,mod-y);
			}
		}
	}
	if(tp==1)return;
	int inv=qpow(lim,mod-2);
	for(int i=0;i<lim;++i)a[i]=mul(a[i],inv);
}
int ans,Ans;
int sa,sb;
signed main(){
	scanf("%lld%lld",&n,&m);
	int lim=1,len=0;
	while(lim<=(n+n+n))lim<<=1,len++;
	for(int i=1;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
	for(int i=0;i<n;++i)scanf("%lld",&a[i]);
	for(int i=0;i<n;++i)scanf("%lld",&b[i]);
	for(int i=0;i<n;++i)ans+=a[i]*a[i]+b[i]*b[i];
	for(int i=0;i<n;++i)sa+=a[i],sb+=b[i];
	sa<<=1,sb<<=1;
	reverse(a,a+n);
	for(int i=n;i<(n<<1);++i)a[i]=a[i-n];
	NTT(a,lim,1);NTT(b,lim,1);
	for(int i=0;i<lim;++i)a[i]=mul(a[i],b[i]);
	int mx=-1;
	NTT(a,lim,-1);
	for(int i=n;i<(n<<1);++i)mx=max(mx,a[i]);
	Ans=(1<<30);
	for(int i=-m;i<=m;++i){Ans=min(Ans,ans-2*mx-sb*i+sa*i+n*i*i);}
	printf("%lld\n",Ans);
	return 0;
} 
posted @ 2021-03-08 12:05  Refined_heart  阅读(44)  评论(0编辑  收藏  举报