zoukankan      html  css  js  c++  java
  • 【[AH2017/HNOI2017]礼物】

    一道神题233。。。其实要是把思路想通了也不是很难。

    正文部分:

    设经过了各种操作之后的数列为(A)(B),总增加量为(x)
    那么第(i)项所造成的影响就是
    ((A_i+x-B_i)^2=A_i^2+x^2+B_i^2+2A_ix-2A_iB_i-2xB_i^2)
    然而(A)手环加上相等于(B)手环减去,所以(m)的范围变为(-100sim100)
    那么我们可以轻松的得到这两个数列的总影响:

    (sum_{i=1}^{i=n}(A_i+x-B_i)^2)

    尝试把这个式子展开,成为:

    (sum_{i=1}^{i=n}A_i^2+sum_{i=1}^{i=n}B_i^2+n*x^2+2x(sum_{i=1}^{i=n}A_i-sum_{i=1}^{i=n}B_i)-2sum_{i=1}^{i=n}A_iB_i)

    这时发现除了最后一项其他项全是固定的,所以我们只需要让最后一项最大即可,可以用(fft)来求解:

    My code

    #include <bits/stdc++.h>
    #define il inline
    #define gc getchar
    #define FI "gift"
    const int MAXN = 4e6 + 10;
    const int INF = 0x7f7f7f7f;
    const double pi = acos(-1);
    using namespace std;
    il int read() {
        int res = 0;char c;bool sign = 0;
        for(c = gc();!isdigit(c);c = gc()) sign |= c == '-';
        for(;isdigit(c);c = gc()) res = (res << 1) + (res << 3) + (c ^ 48);
        return sign ? -res : res;
    }
    il void FileIO() {
        freopen(FI".in","r",stdin);
        freopen(FI".out","w",stdout);
        return;
    }
    struct Cpx {
        double r,i;
        Cpx(){}
        Cpx(double x,double y) {
            r = x,i = y;
        }
        Cpx operator + (const Cpx& x) const {
            return Cpx(r + x.r,i + x.i);
        }
        Cpx operator - (const Cpx& x) const {
            return Cpx(r - x.r,i - x.i);
        }
        Cpx operator * (const Cpx& x) const {
            return Cpx(r * x.r - i * x.i,r * x.i + i * x.r);
        }
        void operator *= (Cpx& x) {
            *this = *this * x;
            return;
        }
    }a[MAXN],b[MAXN];
    int n,m,i,j,k,R[MAXN],_a[MAXN],_b[MAXN];
    int sqr_a,sqr_b,sum_a,sum_b,li,x,ans = INF;
    il void fft(Cpx a[MAXN],int f) {
        int i,j,k;
        for(i = 0;i < li;i++) {
            if(i < R[i]) swap(a[i],a[R[i]]);
        }
        for(i = 1;i < li;i <<= 1) {
            Cpx wn(cos(pi / i),f * sin(pi / i));
            for(j = 0;j < li;j += (i << 1)) {
                Cpx w(1,0);
                for(k = 0;k < i;k++,w *= wn) {
                    Cpx x = a[j + k],y = w * a[j + k + i];
                    a[j + k] = x + y;a[j + k + i] = x - y;
                }
            }
        }
        return;
    }
    int main() {
        // FileIO();
        n = read();m = read();
        for(i = 1;i <= n;i++) {
            _a[i] = read();
            sqr_a += _a[i] * _a[i];
            sum_a += _a[i];
        }
        for(i = 1;i <= n;i++) {
            _b[i] = read();
            sqr_b += _b[i] * _b[i];
            sum_b += _b[i];
        }
        for(i = 1;i <= n;i++) {
            a[i].r = a[i + n].r = _a[i];
            b[i].r = _b[n - i + 1];
        }
        int t = 0;li = 1;while(li <= n*3) li <<= 1,t++;
        for(i = 0;i <= li;i++) {
            R[i] =(R[i >> 1] >> 1 | ((i & 1) << (t - 1)));
        }
        fft(a,1);fft(b,1);
        for(i = 0;i <= li;i++) a[i] *= b[i];
        fft(a,-1);
        for(i = 0;i <= li;i++) {
            a[i].r = (int)(a[i].r / li + 0.5);
        }
        for(i = 1;i <= n;i++) {
            for(x = -m;x <= m;x++) {
                int tmp = sqr_a + sqr_b + n * x * x;
                tmp += 2 * x *(sum_a - sum_b);
                ans = min(ans,tmp - 2 * (int)a[i + n].r);
            }
     	}
     	printf("%lld",1LL * ans);
    }
    
  • 相关阅读:
    【作业】第二周作业, 适合14级1/2班
    【作业】第二周作业,适合13级1/2/3班
    【组织】请13级1/2/3班,14级1/2班 将同学们的博客地址列个清单回复(按班级来)
    【组织】13级1、2、3班和14级1、2班 结对、分组情况请回帖
    【转】没什么能够阻挡,你对自由的向往
    【转】小屁孩, 懂个啥
    【转】远程结对编程实战:看看别人是怎么做的
    【转】看见成长的自己:斯坦福大学心理学教授徳韦克访谈
    【作业】第一周作业
    从std::thread::id取得int值id
  • 原文地址:https://www.cnblogs.com/Sai0511/p/10360596.html
Copyright © 2011-2022 走看看