• 【bzoj4827】[Hnoi2017]礼物【FFT/NTT】


    题目链接
    题解:我们设两个手环增加的数相差c,且已经确定好了排列的顺序。
    则差异值为i=1n(x[i]y[i]+c)2
    =>i=1nx[i]2+y[i]2+c2+2c(x[i]y[i])2x[i]y[i]
    =>i=1nx[i]2+y[i]2+nc2+c×i=1n2(x[i]y[i])2i=1nx[i]y[i]
    我们发现i=1nx[i]2+y[i]2是确定的。nc2+c×i=1n2(x[i]y[i])不就是要求一个二次函数的最小值吗?直接带公式b2a计算。最后我们要求的就是一个排列,使得i=1nx[i]y[i]的值最大。
    我们不妨设第二个手环转了k次。
    则我们要求的就是i=1nx[i]y[i+k]的值。
    把x翻转一下=>i=1nx[ni+1]y[i+k]
    我们发现这是一个卷积的形式。于是我们设两个多项式,把两个多项式乘起来,次数为n+k+1的项代的系数就是转了k次的答案。取个max就好了。最后计算一下上面那个式子的答案就解决了!
    脑抽的我根本没看到x和y是分两行读入的,居然还过了样例,贡献了好几次WA!
    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=270005;
    const double pi=3.141592653589793;
    int n,m,k,x[N],y[N],rev[N]; 
    ll ans,tot,maxn;
    struct complex{
        double x,y;
        complex(){
            x=y=0;
        }
        complex(double x,double y):x(x),y(y){}
        friend complex operator + (const complex &a,const complex &b){
            return complex(a.x+b.x,a.y+b.y);
        }
        friend complex operator - (const complex &a,const complex &b){
            return complex(a.x-b.x,a.y-b.y);
        }
        friend complex operator * (const complex &a,const complex &b){
            return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
        }
    }a[N],b[N];
    void fft(complex *a,int dft){
        for(int i=0;i<k;i++){
            if(i<rev[i]){
                swap(a[i],a[rev[i]]);
            }
        }
        for(int i=1;i<k;i<<=1){
            complex wn=complex(cos(pi/i),dft*sin(pi/i));
            for(int j=0;j<k;j+=i<<1){
                complex w=complex(1,0),x,y;
                for(int l=j;l<j+i;l++,w=w*wn){
                    x=a[l];
                    y=w*a[l+i];
                    a[l]=x+y;
                    a[l+i]=x-y;
                }
            }
        }
        if(dft==-1){
            for(int i=0;i<k;i++){
                a[i].x/=k;
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&x[i]);
            ans+=x[i]*x[i];
            tot+=2*x[i];
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&y[i]);
            ans+=y[i]*y[i];
            tot-=2*y[i];
        }
        double tmp=(-1.0*tot)/(2*n);
        ll l=floor(tmp),r=ceil(tmp);
        if(n*l*l+tot*l<n*r*r+tot*r){
            ans+=n*l*l+tot*l;
        }else{
            ans+=n*r*r+tot*r;
        }
        for(int i=1;i<=n;i++){
            a[i].x=x[n-i+1];
            b[i].x=b[i+n].x=y[i];
        }
        for(k=1;k<=3*n;k<<=1);
        for(int i=0;i<k;i++){
            rev[i]=(rev[i>>1]>>1)|((i&1)*(k>>1));
        }
        fft(a,1);
        fft(b,1);
        for(int i=0;i<k;i++){
            a[i]=a[i]*b[i];
        }
        fft(a,-1);
        for(int i=n+1;i<=2*n;i++){
            maxn=max(maxn,(ll)(a[i].x+0.5));
        }
        ans-=2*maxn;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Sample XPS Documents Download
    触发器中的inserted表和deleted表
    Using freewheel.labs.autodesk.com to auto generate preview images of DWF files on your web site
    解除SQL对组件"Ad Hoc Distributed Queries"的"STATEMENT'OpenRowset OpenDatasource"的访问
    读写xps
    XPS文件,在Windows XP下的打开查看阅读和打印方法。
    Learning to Reference Inserted and Deleted Tables
    Get value from updated, inserted and deleted
    Reinstall Microsoft Helper Viewer
    如何查找文件的IFilter
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476877.html
Copyright © 2020-2023  润新知