4827: [Hnoi2017]礼物

4827: [Hnoi2017]礼物

Time Limit: 60 Sec Memory Limit: 512 MB
Submit: 267 Solved: 196
[Submit][Status][Discuss]
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。

HINT

对一个手环的修改等价于再另一个手环上修改相反数
那么可以假设修改一定发生在第一个手环上
假设第一个手环增加了 d 大力拆开答案的公式
ni=1(xi+dyi)2=ni=1[x2i+y2i+d2+2d(xiyi)2xiyi]
前两项为定值
三四项可以通过枚举 d <script type="math/tex" id="MathJax-Element-3971">d</script>贪心选择最优的
最后一项,将两个手链进行一次NTT,对应系数加一下就行了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = (1 << 17) + 233;
typedef long long LL;
const LL mo = 1004535809;

int n,m,N,Ans,w[maxn],_w[maxn],A[maxn],B[maxn],C[maxn];

inline int Mul(const LL &x,const LL &y) {return x * y % mo;}
inline int Add(const int &x,const int &y) {return x + y < mo ? x + y : x + y - mo;}
inline int Dec(const int &x,const int &y) {return x - y >= 0 ? x - y : x - y + mo;}

int ksm(int x,int y)
{
    int ret = 1;
    for (; y; y >>= 1)
    {
        if (y & 1) ret = Mul(ret,x);
        x = Mul(x,x);
    }
    return ret;
}

void Rader(int *F)
{
    int j = (N >> 1);
    for (int i = 1; i < N - 1; i++)
    {
        if (i < j) swap(F[i],F[j]); int k = (N >> 1);
        while (j >= k) j -= k,k >>= 1; j += k;
    }
}

void NTT(int *F,int *w,int on)
{
    Rader(F);
    for (int k = 2; k <= N; k <<= 1)
        for (int i = 0; i < N; i += k)
        {
            int now = 0;
            for (int j = i; j < i + (k >> 1); j++)
            {
                int u = F[j],v = Mul(F[j + (k >> 1)],w[now]);
                F[j] = Add(u,v); F[j + (k >> 1)] = Dec(u,v); now += N / k;
            }
        }
    if (on == 1) return;
    int Inv = ksm(N,mo - 2);
    for (int i = 0; i < N; i++)
        F[i] = Mul(F[i],Inv);
}

inline int getint()
{
    char ch = getchar(); int ret = 0;
    while (ch < '0' || '9' < ch) ch = getchar();
    while ('0' <= ch && ch <= '9')
        ret = ret * 10 + ch - '0',ch = getchar();
    return ret;
}

int main()
{
    #ifdef DMC
        freopen("DMC.txt","r",stdin);
    #endif

    LL Min = 1E12,tot = 0,Max = 0;
    n = getint(); m = getint(); N = 1;
    for (int i = 0; i < n; i++)
        A[i] = getint(),Ans += A[i] * A[i],tot += A[i];
    for (int i = 0; i < n; i++)
        B[i] = getint(),Ans += B[i] * B[i],tot -= B[i];
    for (int c = -200; c <= 200; c++)
        Min = min(Min,1LL * n * c * c + 2LL * c * tot);
    while (N <= n) N <<= 1; N <<= 1;
    w[0] = 1; w[1] = ksm(3,(mo - 1) / N);
    for (int i = 2; i <= N; i++) w[i] = Mul(w[i - 1],w[1]);
    for (int i = 0; i <= N; i++) _w[i] = w[N - i];
    reverse(B,B + n); NTT(A,w,1); NTT(B,w,1);
    for (int i = 0; i < N; i++) C[i] = Mul(A[i],B[i]);
    NTT(C,_w,-1); int tmp = 2 * n - 1;
    for (int i = n - 1; i >= 0; i--)
        Max = max(Max,1LL * C[i] + C[tmp--]);
    cout << Ans - 2LL * Max + Min << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值