• 【题解】[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)进行卷积,取(iin left{n+1,n+2... ight}[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
    ",Ans);
    	return 0;
    } 
    
  • 相关阅读:
    Linux查看程序端口占用情况
    jQuery冒泡事件阻止
    jQuery中.bind() .live() .delegate() .on()的区别
    Java四种线程池的使用
    JSON数据解析
    判断访问浏览器客户端类型(pc,mac,ipad,iphone,android)
    JAVA单线程和多线程的实现方式
    mysql利用st_distance函数查询附近的点的功能
    Redis缓存数据库常见操作
    JAVA获取CLASSPATH路径
  • 原文地址:https://www.cnblogs.com/h-lka/p/14498948.html
Copyright © 2020-2023  润新知