博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ:4827: [Hnoi2017]礼物

【问题描述】

  我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。

  但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。

   在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n,其中 n 为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手 环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释): ∑(𝑥𝑖 − 𝑦𝑖 ) 2 𝑛 𝑖=1 麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?

【输入格式】

  输入数据的第一行有两个数n, m,代表每条手环的装饰物的数量为n,每个装饰物的初始 亮度小于等于m。

  接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时 针方向上各装饰物的亮度。

【输出格式】

  输出一个数,表示两个手环能产生的最小差异值。

  注意在将手环改造之后,装饰物的亮度 可以大于 m。

【输入样例】

5 6

1 2 3 4 5

6 3 3 4 5

【输入样例】

1

【样例解释】

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

【数据范围】

  30%的数据满足n≤500, m≤10; 70%的数据满足n≤5000; 100%的数据满足1≤n≤50000, 1≤m≤100, 1≤ai≤m。

 

 

写了这么久NTT,现在连FFT都不会写了,是不是药丸啊。

稍微推导可以得到:$d=-\frac{S_x-S_y}{n}$(四舍五入一下)

再做一下循环卷积求出$\sum X_iY_i$的最大值就吼了。

#include<cmath>
#include<cstdio>
#include<algorithm>
#define MN 500001
#define ld double
using namespace std;

int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
const ld pi=4.*atan(1.);
struct na{ld r,i;na(ld _r=0,ld _i=0):r(_r),i(_i){};}A[MN],B[MN],C[MN];
na operator * (na a,na b){return na(a.r*b.r-a.i*b.i,a.r*b.i+b.r*a.i);}
na operator + (na a,na b){return na(a.r+b.r,a.i+b.i);}
na operator - (na a,na b){return na(a.r-b.r,a.i-b.i);}
int n,m,x[MN],y[MN],MMH=0,sx=0,sy=0,d,ma=0,tot;
inline int max(int a,int b){return a>b?a:b;}
void FFT(int N,na a[],int f){
    for (int i=0,j=0;i<N;i++){
        if (i>j) swap(a[i],a[j]);
        for (int k=N>>1;(j^=k)<k;k>>=1);
    }
    for (int i=2;i<=N;i<<=1)
    for (int m=i>>1,j=0;j<N;j+=i){
        na wn=na(cos(2.*pi/i),sin(2.*pi/i)*f),w=na(1,0);
        for (int k=0;k<m;k++){
            na Z=a[j+k+m]*w;
            a[j+k+m]=a[j+k]-Z;
            a[j+k]=a[j+k]+Z;
            w=w*wn;
        }
    }
}
int main(){
    register int i;
    n=read();m=read();
    for (tot=1;tot<(n<<1);tot<<=1);
    for (i=0;i<n;i++) x[i]=read(),sx+=x[i];
    for (i=0;i<n;i++) y[i]=read(),sy+=y[i];
    d=int(round(-1.*(sx-sy)/n));
    for (i=0;i<n;i++) MMH+=(x[i]+d)*(x[i]+d)+y[i]*y[i];
    for (i=0;i<n;i++) A[i]=na(x[n-i-1]+d),B[i]=na(y[i]);
    FFT(tot,A,1);FFT(tot,B,1);
    for (i=0;i<tot;i++) C[i]=A[i]*B[i];
    FFT(tot,C,-1);
    for (i=0;i<n;i++)
    ma=max(ma,int((C[i].r+C[n+i].r)/tot+0.5));
    printf("%d\n",MMH-ma-ma);
}
View Code

 

posted @ 2017-04-21 12:25  swm_sxt  阅读(605)  评论(1编辑  收藏  举报