• 【LG3723】[AHOI2017/HNOI2017]礼物


    【LG3723】[AHOI2017/HNOI2017]礼物

    题面

    洛谷

    题解

    首先我们将(c)看作一个可以为负的整数,那么我们就可以省去讨论在哪个手环加(c)的繁琐步骤了

    设我们当前已经选好了手环的顺序

    [Ans=sum_{i=1}^n(x_i-y_i+c)^2\ =sum_{i=1}^nx_i^2+sum_{i=1}^ny_i^2+n*c^2+2csum_{i=1}^n(x_i-y_i)-2sum_{i=1}^nx_i*y_i ]

    实际上,因为前面都是定值((C)的取值可以枚举),所以要求

    [sum_{i=1}^nx_i*y_i ]

    最大就行了。

    我们将(y_i)反向,那么原式就是一个卷积。

    这里有个很巧妙的(trick):将(y)再倍长一下,取(x*y)中第(n+1)(2n)项的最小值即可,这样

    就很巧妙地模拟了翻转的过程

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    inline int gi() {
    	register int data = 0, w = 1;
    	register char ch = 0;
    	while (!isdigit(ch) && ch != '-') ch = getchar(); 
    	if (ch == '-') w = -1, ch = getchar();
    	while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    	return w * data; 
    }
    const double PI = acos(-1.0);
    const int MAX_N = 2000005; 
    struct Complex { double x, y; } a[MAX_N], b[MAX_N]; 
    inline Complex operator + (const Complex &l, const Complex &r) { return (Complex){l.x + r.x, l.y + r.y}; }
    inline Complex operator - (const Complex &l, const Complex &r) { return (Complex){l.x - r.x, l.y - r.y}; }
    inline Complex operator * (const Complex &l, const Complex &r) { return (Complex){l.x * r.x - l.y * r.y, l.y * r.x + l.x * r.y}; } 
    int n, m, N, M, s1[MAX_N], s2[MAX_N], r[MAX_N], res[MAX_N]; 
    void FFT(Complex *p, int op) { 
    	for (int i = 0; i < N; i++) if (i < r[i]) swap(p[i], p[r[i]]); 
    	for (int i = 1; i < N; i <<= 1) {
    		Complex rot = (Complex){cos(PI / i), op * sin(PI / i)};
    		for (int tmp = i << 1, j = 0; j < N; j += tmp) { 
    			Complex w = (Complex){1, 0}; 
    			for (int k = 0; k < i; k++, w = w * rot) { 
    				Complex x = p[j + k], y = w * p[i + j + k]; 
    				p[j + k] = x + y, p[i + j + k] = x - y; 
    			} 
    		} 
    	} 
    } 
    void Prepare () { 
    	N = n - 1, M = n + n - 1; 
    	for (int i = 0; i <= N; i++) a[i].x = s1[i + 1]; 
    	for (int i = 0; i < n; i++) b[i].x = s2[n - i]; 
    	for (int i = 0; i < n; i++) b[i + n] = b[i];
    	int P = 0; 
    	for (M += N, N = 1; N <= M; N <<= 1, ++P) ; 
    	for (int i = 0; i < N; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (P - 1)); 
    	FFT(a, 1), FFT(b, 1); 
    	for (int i = 0; i < N; i++) a[i] = a[i] * b[i]; 
    	FFT(a, -1); 
    	for (int i = 0; i <= M; i++) res[i] = (int)(a[i].x / N + 0.5); 
    } 
    int main () {
    	n = gi(), m = gi(); 
    	for (int i = 1; i <= n; i++) s1[i] = gi(); 
    	for (int i = 1; i <= n; i++) s2[i] = gi(); 
    	Prepare(); 
    	int p1 = 0, p2 = 0, ans = 1e9, tmp1 = 0, tmp2 = 0, tt = -1e9;
    	for (int i = 1; i <= n; i++) p1 += s1[i] * s1[i], p2 += s2[i] * s2[i], tmp1 += s1[i], tmp2 += s2[i]; 
    	for (int i = n - 1; i < n + n; i++) tt = max(tt, res[i]); 
    	for (int C = -m; C <= m; C++) {
    		int tot = p1 + p2 + n * C * C + 2 * C * (tmp1 - tmp2) - 2 * tt; 
    		ans = min(tot, ans); 
    	} 
    	printf("%d
    ", ans); 
    	return 0; 
    } 
    
  • 相关阅读:
    UVa 1331 最大面积最小的三角剖分
    UVa 1626 括号序列(矩阵连乘)
    POJ 3295 Tautology(构造法)
    POJ 2586 Y2K Accounting Bug(贪心)
    POJ 2109 Power of Cryptography
    abcd
    好数
    Gift
    密码游戏
    约瑟夫游戏
  • 原文地址:https://www.cnblogs.com/heyujun/p/10334711.html
Copyright © 2020-2023  润新知