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

【文文殿下】[AH2017/HNOI2017]禮物

for tdi con fft while swap r+ main b+

題解

二項式展開,然後暴力FFT就好了。會發現有一個卷積與c無關,我們找一個最小的項就行了。

Tips:記得要倍長其中一個數組,防止FFT出鍋

代碼如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e4+10;
const double pi = acos(-1.0);
struct Complex{
    double r,i;
    Complex(double r,double i):r(r),i(i){}
    Complex(){}
} A[maxn<<4],B[maxn<<4];
Complex operator + (Complex a,Complex b) {
    return Complex(a.r+b.r,a.i+b.i);
}
Complex operator - (Complex a,Complex b) {
    return Complex(a.r-b.r,a.i-b.i);
}
Complex operator * (Complex a,Complex b) {
    return Complex(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);
}
void operator *= (Complex &a,Complex b) {
    a=a*b;
}
void fft(Complex *a,int n,int inv) {
    for(int i = 1,j=n>>1;i<n-1;++i) {
        if(i<j) swap(a[i],a[j]);
        int k = n>>1;
        while(j>=k) j-=k,k>>=1;
        j+=k;
    }
    for(int j = 2;j<=n;j<<=1) {
        Complex wn(cos(2*pi/j*inv),sin(2*pi/j*inv));
        for(int i = 0;i<n;i+=j) {
            Complex w(1,0);
            for(int k = i;k<i+(j>>1);++k) {
                Complex u(a[k]),t(a[k+(j>>1)]*w);
                a[k]=u+t;
                a[k+(j>>1)]=u-t;
                w*=wn;
            }
        }
    }
    if(inv == -1) 
        for(int i = 0;i<n;++i) a[i].r/=n;
}
int n,m;
int a[maxn],b[maxn];
ll aa,bb,sa,sb;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i = 0;i<n;++i) cin>>a[i];
    for(int i = 0;i<n;++i) cin>>b[i];
    for(int i = 0;i<n;++i) {
        aa+=a[i]*a[i];
        bb+=b[i]*b[i];
        sa+=a[i];
        sb+=b[i];
    }
    for(int i = 0;i<n;++i) A[n-i].r=a[i],B[i].r=B[i+n].r=b[i];
    int lmt = 1;
    while(lmt<=2*n) lmt<<=1;
    fft(A,lmt,1);fft(B,lmt,1);
    for(int i = 0;i<lmt;++i) A[i]*=B[i];
    fft(A,lmt,-1);
    ll mn = 0;
    for(int i = 0;i<2*n;++i) {
        mn = max(mn , (ll)(A[i].r+0.5));
    }
    ll ans = 10000000000000000LL;
    for(int c = -m;c<=m;++c) {
        ll cc = 1LL*n*c*c;
        ans = min(ans , aa+bb+cc+2LL*sa*c-2LL*sb*c-2LL*mn);
    }
    cout<<ans<<endl;
    return 0;
}

【文文殿下】[AH2017/HNOI2017]禮物