zoukankan      html  css  js  c++  java
  • bzoj 4827: [Hnoi2017]礼物

    枚举对一个环整体加上的值c=-m~m,则答案

    $sum_{i=0}^{n-1}{(a_i-b_{(i+d)\%n}+c)^2}$

    $=sum_{i=0}^{n-1}{(a_i^2+b_i^2+c^2-2cb_i+2ca_i-2a_ib_{(i+d)\%n})}$

    其中只有$sum_{i=0}^{n-1}{a_ib_{(i+d)\%n}}$一项不能直接计算,但可以看出这是循环卷积的形式,用fft求出对每个d的答案,再取最大值即可

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define G *++ptr
    char buf[2000000],*ptr=buf-1;
    int _(){
        int x=0,c=G;
        while(c<48)c=G;
        while(c>47)x=x*10+c-48,c=G;
        return x;
    }
    const int M=133333;
    const double _2pi=acos(-1)*2;
    struct cplx{
        double a,b;
        cplx(double _a=0,double _b=0):a(_a),b(_b){}
        cplx operator+(cplx x){return cplx(a+x.a,b+x.b);}
        cplx operator-(cplx x){return cplx(a-x.a,b-x.b);}
        cplx operator*(cplx x){return cplx(a*x.a-b*x.b,a*x.b+b*x.a);}
    }A[M],B[M],e[2][M];
    int N,P;
    int n,m,r[M],a[50007],b[50007],a2=0,a1=0,b2=0,b1=0,ans=0x7fffffff,ab=0;
    void dft(cplx*a,int t){
        for(int i=0;i<N;++i)if(i<r[i])std::swap(a[i],a[r[i]]);
        for(int i=1;i<N;i<<=1){
            for(int j=0,z=N/(i<<1);j<N;j+=i<<1){
                cplx*b=a+j,*c=b+i;
                for(int k=0;k<i;++k){
                    cplx x=b[k],y=c[k]*e[t][k*z];
                    b[k]=x+y;
                    c[k]=x-y;
                }
            }
        }
        if(t)for(int i=0;i<N;++i)a[i].a/=N;
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin)[buf]=0;
        n=_();m=_();
        for(int i=0;i<n;++i)a[i]=_(),a2+=a[i]*a[i],a1+=a[i];
        for(int i=0;i<n;++i)b[i]=_(),b2+=b[i]*b[i],b1+=b[i];
        for(N=2,P=0;N<n*2+3;N<<=1,++P);
        for(int i=1;i<N;++i)r[i]=r[i>>1]>>1|(i&1)<<P;
        for(int i=0;i<N;++i){
            e[0][i]=cplx(cos(i*_2pi/N),sin(i*_2pi/N));
            e[1][i]=cplx(cos(i*_2pi/N),-sin(i*_2pi/N));
        }
        for(int i=0;i<n;++i)A[i]=a[n-1-i],B[i]=b[i];
        dft(A,0);dft(B,0);
        for(int i=0;i<N;++i)A[i]=A[i]*B[i];
        dft(A,1);
        for(int i=n;i<n*2;++i){
            int v=int(A[i].a+A[i-n].a+0.49);
            if(v>ab)ab=v;
        }
        for(int c=-m;c<=m;++c){
            int v=a2+b2+c*c*n-2*b1*c+2*a1*c-2*ab;
            if(v<ans)ans=v;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    flash中网页跳转总结
    as3自定义事件
    mouseChildren启示
    flash拖动条移出flash无法拖动
    需要一个策略文件,但在加载此媒体时未设置checkPolicyFile标志
    Teach Yourself SQL in 10 Minutes
    电子书本地转换软件 Calibre
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes – Page 31 练习
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6727686.html
Copyright © 2011-2022 走看看