HNOI2017礼物

礼物
  • 这估计是最水,最无脑的一道题了
  • 首先发现总和最接近时答案最小
  • 发现答案就是\((\sum_{i=1}^{n}a[i]^2+b[i]^2)-2*max(\sum_{i=1}^{n}a[i]*b[i+j])(0<=j<=n-1)\)
  • 前面随便算,主要是后面那个式子,其实就是两个数列错位相乘加起来最大值
  • 把\(b\)反过来就变成\(\sum_{i=1}^{n}a[i]*b[n-i-j])(0<=j<=n-1)\),直接就多项式卷积,FFT一算就行了。
    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=5e4+5;
    bool cmax(ll &a,ll b){return (a<b)?a=b,1:0;}
    bool cmin(ll &a,ll b){return (a>b)?a=b,1:0;}
    template<typename T>inline T read()
    {
    T f=1,ans=0;
    char ch=getchar();
    while(!isdigit(ch)&&ch!=‘-‘)ch=getchar();
    if(ch==‘-‘)f=-1,ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-‘0‘),ch=getchar();
    return ans*f;
    }
    template<typename T>inline void write(T x,char y)
    {
    if(x==0)
    {
        putchar(‘0‘);putchar(y);
        return;
    }
    if(x<0)
    {
        putchar(‘-‘);
        x=-x;
    }
    static char wr[20];
    int top=0;
    for(;x;x/=10)wr[++top]=x%10+‘0‘;
    while(top)putchar(wr[top--]);
    putchar(y);
    }
    void file()
    {
    #ifndef ONLINE_JUDGE
        freopen("3723.in","r",stdin);
        freopen("3723.out","w",stdout);
    #endif
    }
    struct comp
    {
    double r,v;
    comp operator + (const comp &x) const {return (comp){r+x.r,v+x.v};}
    comp operator - (const comp &x) const {return (comp){r-x.r,v-x.v};}
    comp operator * (const comp &x) const {return (comp){r*x.r-v*x.v,r*x.v+v*x.r};}
    };
    comp a[N<<2],b[N<<2];
    int m,n,t;
    int rev[N<<2];
    int sum1,sum2;
    void input()
    {
    n=read<int>();t=read<int>();m=n-1;
    For(i,0,m)a[i].r=read<int>(),sum1+=a[i].r;
    For(i,0,m)b[m-i].r=read<int>(),sum2+=b[m-i].r;
    }
    void init()
    {
    if(sum1>sum2)swap(a,b),swap(sum1,sum2);
    int temp=(sum2-sum1)/n;
    if(sum1+(temp+1)*n-sum2<sum2-sum1-temp*n)temp++;
    For(i,0,m)a[i].r+=temp;
    m<<=1;
    int cnt=0;
    for(n=1;n<=m;n<<=1)cnt++;
    for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(1<<(cnt-1)));
    }
    const double pi=acos(-1.0);
    ll ans;
    void FFT(comp *p,int type)
    {
    int i,j,k,num;
    for(i=0;i<n;i++)if(i<rev[i])swap(p[i],p[rev[i]]);
    for(i=2;i<=n;i<<=1)
    {
        comp wi={cos(pi*2/i),sin(pi*2/i)*type};
        num=i>>1;
        for(j=0;j<n;j+=i)
        {
            comp x={1,0};
            for(k=0;k<num;k++,x=x*wi)
            {
                comp u=p[j+k],v=p[j+k+num]*x;
                p[j+k]=u+v;
                p[j+k+num]=u-v;
            }
        }
    }
    }
    int w[N<<2];
    void work()
    {
    //For(i,0,m>>1)write((int)a[i].r,i==m/2?‘\n‘:‘ ‘);
    //For(i,0,m>>1)write((int)b[i].r,i==m/2?‘\n‘:‘ ‘);
    ll res=0;
    For(i,0,m>>1)ans+=a[i].r*a[i].r+b[i].r*b[i].r;
    FFT(a,1);FFT(b,1);
    for(int i=0;i<n;i++)a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0;i<n;i++)w[i]=(int)(a[i].r/n+0.5);
    m>>=1;
    For(i,0,m-1)cmax(res,w[i]+w[i+m+1]);
    write(ans-res*2,‘\n‘);
    }
    int main()
    {
    file();
    input();
    init();
    work();
    return 0;
    }

原文地址:https://www.cnblogs.com/dengyixuan/p/8361950.html

时间: 2024-08-10 18:22:52

HNOI2017礼物的相关文章

BZOJ4827: [Hnoi2017]礼物

4827: [Hnoi2017]礼物 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 474  Solved: 334[Submit][Status][Discuss] Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在她生日的前一天,我的室友突 然发现他好像拿错了一个手环,而且已经没时间去更换它了

[bzoj4827][Hnoi2017]礼物_FFT

礼物 bzoj-4827 Hnoi-2017 题目大意:给定两个长度为$n$的手环,第一个手环上的$n$个权值为$x_i$,第二个为$y_i$.现在我可以同时将所有的$x_i$同时加上自然数$c$.我也可以将第一个手环任意旋转.旋转后每一个$x$对应一个$y$,那么代价为$\sum\limits_{i=0}^{n-1} (x_i-y_i)^2$.求最小代价. 注释:$1\le n\le 10^5$,$0\le maxval \le 100$. 想法: 水题啊..... 推推式子,我们假设就加了$

[HNOI2017]礼物

题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度. 但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数).并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转.需要在经过亮度改造和旋转之后,使得

bzoj 4827: [HNOI2017]礼物 (FFT)

一道FFT 然而据说暴力可以水70分 然而我省选的时候看到了直接吓傻了  连暴力都没打 太弱了啊QAQ emmmm 详细的拆开就看其他题解吧233 最后那一步卷积其实我一直没明白 后来画画图终于懂了 只要把其中一个反过来 多项式乘法的结果中的每一项系数就对应某一个Σx[i] * y[j] 的结果 前面几项是不完全的结果 但是太小了就被忽略啦 代码如下 /************************************************************** Problem:

[BZOJ 4827][Hnoi2017]礼物(FFT)

Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在她生日的前一天,我的室友突 然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有 装饰物的亮度增加一个相同的自然数 c(即非负整数).并且由于这个手环是一个圆,可以以任意的角度旋转它, 但是由于上面 装饰物的方向是固定的,所以手环不能翻转.需要在经过

[AH/HNOI2017]礼物

题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度. 但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数).并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转.需要在经过亮度改造和旋转之后,使得

BZOJ 4827 [Hnoi2017]礼物 ——FFT

题目上要求一个循环卷积的最小值,直接破环成链然后FFT就可以了. 然后考虑计算的式子,可以分成两个部分分开计算. 前半部分FFT,后半部分扫一遍. #include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <alg

【bzoj4827】[Hnoi2017]礼物 FFT

题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在她生日的前一天,我的室友突 然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有 装饰物的亮度增加一个相同的自然数 c(即非负整数).并且由于这个手环是一个圆,可以以任意的角度旋转它, 但是由于上面 装饰物的方向是固定的,所以手环不能翻转.需要在经过亮度改造和旋转

BZOJ4827 [Hnoi2017]礼物 多项式 FFT

原文链接http://www.cnblogs.com/zhouzhendong/p/8823962.html 题目传送门 - BZOJ4827 题意 有两个长为$n$的序列$x$和$y$,序列$x,y$的第$i$项分别是$x_i,y_i$. 选择一个序列$A$,现在你可以对它进行如下两种操作: $1.$ 得到一个和$A$循环同构的序列$A'$. $2.$ 给所有的$A'_i$都加上$c(c\in N^+)$,得到序列$A''$. 你进行上面两个操作之后,得到的序列分别为$x'',y''$(注意$