1. 程式人生 > >【[AH2017/HNOI2017]禮物】

【[AH2017/HNOI2017]禮物】

include names pan int sig lin i++ std const

一道神題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\)的範圍變為\(-100\sim100\)
那麽我們可以輕松的得到這兩個數列的總影響:

\(\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)-2\sum_{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);
}

【[AH2017/HNOI2017]禮物】