• bzoj4827 [Hnoi2017]礼物


    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。

    Sample Input

    5 6
    1 2 3 4 5
    6 3 3 4 5

    Sample Output

    1
    【样例解释】
    需要将第一个手环的亮度增加1,第一个手环的亮度变为: 2 3 4 5 6 旋转一下第二个手环。对于该样例,是将第二个手环的亮度6 3 3 4 5向左循环移动 2017-04-15 第 6 页,共 6 页 一个位置,使得第二手环的最终的亮度为:3 3 4 5 6。 此时两个手环的亮度差异值为1。

    正解:$FFT$。

    考场上切了这题,还是很高兴的。。

    首先我们可以发现,一个手环最多$+m$,我们只要分别枚举每个手环加多少就行了。

    我们只考虑$x$手环加数,因为$y$手环与$x$手环其实是一样的。

    枚举$m$,那么$Ans=sum_{i=1}^{n}(x_{i}+m-y_{i})^{2}$。我们把它拆开以后可以发现,$Ans=sum_{i=1}^{n}(x_{i}+m)^{2}+y_{i}^{2}-2*y_{i}*x_{i}-2*y_{i}*m$。

    容易发现,$2*x_{i}*y_{i}$是复杂度的瓶颈。其实这一项可以很容易看出是一个卷积,我们把另一个数组翻转一下,就能发现$sum_{i=1}^{n}x_{i}*y_{i}$是一个卷积的形式,然后直接上$FFT$就能过了。

    其实这题还有复杂度更优的$O(nlogn+n)$的做法,似乎是用二次函数的最值??不过$O(nlogn+nm)$也能过。。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <complex>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <set>
      8 #define inf (2147483647)
      9 #define N (100010)
     10 #define il inline
     11 #define RG register
     12 #define ll long long
     13 #define C complex <long double>
     14 
     15 using namespace std;
     16 
     17 const long double pi=acos(-1.0);
     18 
     19 int a[N],b[N],n,m;
     20 
     21 il int gi(){
     22   RG int x=0,q=1; RG char ch=getchar();
     23   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     24   if (ch=='-') q=-1,ch=getchar();
     25   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     26   return q*x;
     27 }
     28 
     29 namespace brute{
     30 
     31   int ans,res1,res2;
     32   
     33   il void work(){
     34     ans=inf;
     35     for (RG int i=1;i<=n;++i) a[i]=gi(),a[n+i]=a[i],res1+=a[i]*a[i];
     36     for (RG int i=1;i<=n;++i) b[i]=gi(),b[n+i]=b[i],res2+=b[i]*b[i];
     37     for (RG int k=0;k<=m;++k){
     38       for (RG int i=1;i<=n;++i) a[i]+=k;
     39       for (RG int i=1;i<=n;++i){
     40     RG int res=0;
     41     for (RG int j=1;j<=n;++j) res+=(a[j]-b[i+j-1])*(a[j]-b[i+j-1]);
     42     ans=min(ans,res);
     43       }
     44       for (RG int i=1;i<=n;++i) a[i]-=k;
     45     }
     46     for (RG int k=0;k<=m;++k){
     47       for (RG int i=1;i<=n;++i) b[i]+=k;
     48       for (RG int i=1;i<=n;++i){
     49     RG int res=0;
     50     for (RG int j=1;j<=n;++j) res+=(b[j]-a[i+j-1])*(b[j]-a[i+j-1]);
     51     ans=min(ans,res);
     52       }
     53       for (RG int i=1;i<=n;++i) b[i]-=k;
     54     }
     55     printf("%d
    ",ans); return;
     56   }
     57   
     58 }
     59 
     60 namespace cheat{
     61   
     62   C A[4*N],B[4*N];
     63   int rev[4*N],NN,lg;
     64   ll r1[N],r2[N],res1,res2,tot1,tot2,ans;
     65   
     66   il void fft(C *a,RG int n,RG int f){
     67     for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]);
     68     for (RG int i=1;i<n;i<<=1){
     69       C wn(cos(pi/i),sin(f*pi/i)),x,y;
     70       for (RG int j=0;j<n;j+=(i<<1)){
     71     C w(1,0);
     72     for (RG int k=0;k<i;++k,w*=wn){
     73       x=a[j+k],y=w*a[j+k+i];
     74       a[j+k]=x+y,a[j+k+i]=x-y;
     75     }
     76       }
     77     }
     78     return;
     79   }
     80   
     81   il void work(){
     82     for (RG int i=1;i<=n;++i){
     83       a[i]=gi(),A[i]=a[i];
     84       res1+=a[i]*a[i],tot1+=a[i];
     85     }
     86     for (RG int i=1;i<=n;++i){
     87       b[i]=gi(),B[n-i+1]=b[i];
     88       res2+=b[i]*b[i],tot2+=b[i];
     89     }
     90     for (NN=1;NN<=(n<<1);NN<<=1) lg++; ans=1LL<<60;
     91     for (RG int i=0;i<NN;++i) rev[i]=rev[i>>1]>>1|((i&1)<<(lg-1));
     92     fft(A,NN,1),fft(B,NN,1);
     93     for (RG int i=0;i<NN;++i) A[i]*=B[i]; fft(A,NN,-1);
     94     for (RG int i=n+1;i<=(n<<1);++i){
     95       r1[i-n]=(ll)(A[i].real()/NN+0.5);
     96       r1[i-n]+=(ll)(A[i-n].real()/NN+0.5);
     97     }
     98     memset(A,0,sizeof(A)),memset(B,0,sizeof(B));
     99     for (RG int i=1;i<=n;++i) A[n-i+1]=a[i],B[i]=b[i];
    100     fft(A,NN,1),fft(B,NN,1);
    101     for (RG int i=0;i<NN;++i) B[i]*=A[i]; fft(B,NN,-1);
    102     for (RG int i=n+1;i<=(n<<1);++i){
    103       r2[i-n]=(ll)(B[i].real()/NN+0.5);
    104       r2[i-n]+=(ll)(B[i-n].real()/NN+0.5);
    105     }
    106     for (RG ll k=0;k<=m;++k){
    107       RG ll cnt=res2;
    108       for (RG int i=1;i<=n;++i) cnt+=(a[i]+k)*(a[i]+k);
    109       for (RG int i=1;i<=n;++i) ans=min(ans,cnt-2*(r1[i]+tot2*k));
    110     }
    111     for (RG ll k=0;k<=m;++k){
    112       RG ll cnt=res1;
    113       for (RG int i=1;i<=n;++i) cnt+=(b[i]+k)*(b[i]+k);
    114       for (RG int i=1;i<=n;++i) ans=min(ans,cnt-2*(r2[i]+tot1*k));
    115     }
    116     printf("%lld
    ",ans); return;
    117   }
    118   
    119 }
    120 
    121 il void work(){  
    122   n=gi(),m=gi();
    123   if (n<=500 && m<=10){ brute::work(); return; }
    124   cheat::work(); return;
    125 }
    126 
    127 int main(){
    128   freopen("gift.in","r",stdin);
    129   freopen("gift.out","w",stdout);
    130   work();
    131   return 0;
    132 }
  • 相关阅读:
    Unity接入九游SDK学习与踩坑
    Linux系统下实现Tomcat的安装和项目的部署:
    mac查看端口占用情况并结束进程
    BootStrap
    ES6
    JQuery
    CSS 、JavaScript
    HTML
    XML
    数据库连接池&DBUtils
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6785521.html
Copyright © 2020-2023  润新知