• BZOJ 4827: [Hnoi2017]礼物 FFT


    Description

    我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一
    个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突
    然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有
    装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,
    但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差
    异值最小。在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n,
    其中 n 为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手 环的 i 号位置装饰物
    亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释): sum_{i=1}^{n}(x_i-y_i)^2麻烦你帮他
    计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?

    Input

    输入数据的第一行有两个数n, m,代表每条手环的装饰物的数量为n,每个装饰物的初始 亮度小于等于m。
    接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时 针方向上各装饰物的亮度。
    1≤n≤50000, 1≤m≤100, 1≤ai≤m

    Output

    输出一个数,表示两个手环能产生的最小差异值。
    注意在将手环改造之后,装饰物的亮度 可以大于 m。

    题解:

    最小化 $sum_{i=1}^{n}(x_{i}-y_{i}+c)^2$
     
    $Rightarrow sum_{i=1}^{n}x_{i}^2+sum_{i=1}^{n}y_{i}^2+2c(sum_{i=1}^{n}x_{i}-sum_{i=1}^{n}y_{i})+c^2-2sum_{i=1}^{n}x_{i}y_{i+k}$
     
    发现前面 $sum_{i=1}^{n}x_{i}^2+sum_{i=1}^{n}y_{i}^2$ 是定值,$2c(sum_{i=1}^{n}x_{i}-sum_{i=1}^{n}y_{i})+c^2$ 可以用二次函数解决

    后面的 $sum_{i=1}^{n}x_{i}y_{i+k}$ 可以令 $x$ 翻转,即 $x_{i}=x_{n-1-i}, sum_{i=1}^{n}x_{n-1-i}y_{i+k}$
     
    用 $FFT$ 加速多项式乘法,依次枚举这个 $k$,取一下最大值即可 
    #include <bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 3100000
    #define ll long long 
    using namespace std;
    namespace FFT
    {
        #define pi 3.1415926535898 
        struct cpx
        {
            double x,y; 
            cpx(double a=0,double b=0){x=a,y=b;} 
        }; 
        cpx operator+(cpx a,cpx b) { return cpx(a.x+b.x,a.y+b.y); }
        cpx operator-(cpx a,cpx b) { return cpx(a.x-b.x,a.y-b.y); } 
        cpx operator*(cpx a,cpx b) { return cpx(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x); }
        void FFT(cpx *a,int n,int flag)
        {
            for(int i = 0,k = 0;i < n; ++i)
            {
                if(i > k) swap(a[i],a[k]);
                for(int j = n >> 1;(k^=j)<j;j>>=1);
            }
            for(int mid=1;mid<n;mid<<=1)
            {
                cpx wn(cos(pi/mid),flag*sin(pi/mid)),x,y; 
                for(int j=0;j<n;j+=(mid<<1)) 
                {
                    cpx w(1,0); 
                    for(int k=0;k<mid;++k) 
                    {
                        x = a[j+k],y=w*a[j+mid+k]; 
                        a[j+k]=x+y; 
                        a[j+mid+k]=x-y; 
                        w=w*wn; 
                    }
                }
            }
            if(flag==-1)  for(int i=0;i<n;++i) a[i].x/=(double)n; 
        }
        cpx A[maxn],B[maxn]; 
        void mult(int *a,int *b,int len)
        {
            int m = 1;
            while(m <= len) m <<= 1; 
            for(int i = 0;i < len; ++i) A[i].x = (double)a[i]; 
            for(int i = 0;i < len; ++i) B[i].x = (double)b[i]; 
            FFT(A,m,1),FFT(B,m,1); 
            for(int i = 0;i < m; ++i) A[i] = A[i] * B[i]; // , printf("%.2f
    ",A[i].x); 
            FFT(A,m,-1);  
            for(int i = 0;i < len; ++i) a[i] = (int)(A[i].x + 0.5); 
        }
    }; 
    int arr[maxn],brr[maxn],n,m,t; 
    ll ans = 0; 
    int main()
    {
        // setIO("input"); 
        scanf("%d%d",&n,&m);
        for(int i = 0;i < n; ++i) scanf("%d",&arr[i]); 
        for(int i = 0;i < n; ++i) scanf("%d",&brr[i]); 
        for(int i = 0;i < n; ++i) 
        {
            ans += 1ll*arr[i]*arr[i] + 1ll*brr[i]*brr[i]; 
            t += brr[i]-arr[i]; 
        }
        int c1 = floor(t*1.0/n), c2 = ceil(t*1.0/n); 
        ans += min(1ll*c1*c1*n - 1ll*c1*2*t, 1ll*c2*c2*n - 1ll*c2*2*t);       
        reverse(&arr[0],&arr[n]);
        for(int i = n;i < 2*n;++i) brr[i]=brr[i-n]; 
        FFT::mult(brr,arr,3*n);      
        int tmp = 0;
        for(int i = 0;i < n; ++i) tmp = max(tmp,brr[i + n]) ; 
        ans -= (tmp<<1); 
        printf("%lld
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    摄影技巧:如何拍好夜景?这些拍摄要点值得借鉴
    单反摄影:快门优先怎么用?
    摄影基础知识:什么是光圈优先?
    【震惊】、【无耻】、【嚣张】浙江谷誉科技旗下爱卡之家,黑商圈钱跑路,强行黑吃,用户损失累计数亿
    爱卡之家是不是骗人的,爱卡之家跑路了吗?
    浙江谷誉网络的爱卡之家怎么样,是不是真实的,靠不靠谱?
    爱卡之家app怎么样?爱卡之家油卡套餐可信吗?爱卡之家是不是骗人的,靠不靠谱?
    爱卡之家充值不到账 爱卡之家疑似跑路 爱卡之家客服联系不上
    android TypedValue.applyDimension()的作用
    Android 在xml中配置 float 和 integer 值
  • 原文地址:https://www.cnblogs.com/guangheli/p/10937498.html
Copyright © 2020-2023  润新知