zoukankan      html  css  js  c++  java
  • [AH2017/HNOI2017]礼物 (FFT)

    题面

    LOJ传送门

    题解

    直接把贡献写出来看看。

    [sum_{i=1}^n(a_i-b_i+x)^2=sum_{i=1}^n(a_i^2+b_i^2)+nx^2+2xsum_{i=1}^n(a_i-b_i)-2sum_{i=1}^na_ib_i ]

    发现当(x)已知时,唯一需要考虑的就是最后一项,因为可以循环位移数组。然后由于(x)值域([-m,m])可枚举,那么问题就在于怎么求(maxsum_{i=1}^na_ib_i)

    我们把(a)数组倍长,就是求(max_{i=1}^{n}sum_{j=1}^na_{i+j-1}b_j)

    (b)数组倒序,就是求(max_{i=1}^{n}sum_{j=1}^na_{i+j-1}b_{n-j+1})

    那么这就是一个卷积的形式,直接(FFT)乘起来求第(n+1)(2*n)项的最大值就行了。最后再枚举(x)求答案。实际上不用枚举,直接二次函数对称轴,不过(m)只有(100),随便做了。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = (1<<18) + 5;
    const double Pi = acos(-1.0);
    int n, m, a[MAXN], b[MAXN];
    LL sa, sb, s2;
    struct cp {
    	double x, y;
    	cp(){}
    	cp(double xx, double yy):x(xx), y(yy){}
    	inline cp operator+(const cp &o)const { return cp(x+o.x, y+o.y); }
    	inline cp operator-(const cp &o)const { return cp(x-o.x, y-o.y); }
    	inline cp operator*(const cp &o)const { return cp(x*o.x-y*o.y, x*o.y+y*o.x); }
    }f[MAXN], g[MAXN];
    int rev[MAXN];
    void FFT(cp *arr, int len, int flg) {
    	for(int i = 0; i < len; ++i)if(rev[i]<i)swap(arr[i], arr[rev[i]]);
    	cp u, v, wn, w;
    	for(int i = 2; i <= len; i<<=1) {
    		wn = cp(cos(2*Pi/i*flg), sin(2*Pi/i*flg));
    		for(int j = 0; j < len; j += i) {
    			w = cp(1, 0);
    			for(int k = j; k < j + i/2; ++k) {
    				u = arr[k];
    				v = arr[k+i/2]*w;
    				arr[k] = u + v;
    				arr[k+i/2] = u - v;
    				w = w * wn;
    			}
    		}
    	}
    	if(flg == -1) for(int i = 0; i < len; ++i) arr[i].x/=len;
    }
    int main () {
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), sa += a[i], s2 += a[i]*a[i], a[n+i] = a[i];
    	for(int i = n; i >= 1; --i) scanf("%d", &b[i]), sb += b[i], s2 += b[i]*b[i];
    	int len = 1; while(len <= (3*n)) len<<=1;
    	for(int i = 1; i < len; ++i) rev[i] = (rev[i>>1]>>1)|((i&1)*(len>>1));
    	for(int i = 0; i < len; ++i) f[i] = cp(a[i], 0), g[i] = cp(b[i], 0);
    	FFT(f, len, 1), FFT(g, len, 1);
    	for(int i = 0; i < len; ++i) f[i] = f[i] * g[i];
    	FFT(f, len, -1);
    	LL mx = 0, ans = 1ll<<50;
    	for(int i = n+1; i <= 2*n; ++i)
    		mx = max(mx, (LL)round(f[i].x));
    	for(LL x = -m; x <= m; ++x)
    		ans = min(ans, s2 + n*x*x + 2*x*(sa-sb) - 2*mx);
    	printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    澳洲中产收入水平[转]
    [转载]在澳洲做IT人士的收入差别
    取消excel 工作保护 密码的宏
    SAP ML 物料分类账详解(含取消激活物料帐方法)
    ABAP--如何创建自定义打印条码
    SAP 产品条码WMS结合 以及ABAP script的集成 BarCode
    SAP 以工序为基准进行发料 机加工行业 Goods Issue to Routing
    SAP HR模块的基础数据表和增强配置
    SAP财务供应链与金库管理的联系与区别
    评点SAP HR功能及人力资源管理软件
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12091944.html
Copyright © 2011-2022 走看看