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''$(注意$x,y$两个序列中至少有一个序列没有发生任何变化)
序列$x''$和$y''$的差异值为
$$\sum_{i=1}^{n}(x''_i-y''_i)^2$$
问差异值最小为多少。
题解
我们可以选择任何一个序列进行那两个操作就是相当于对$x$进行操作$1$和下面这个操作:
$2'.$ 给所有的$x'_i$都加上$c(c\in Z)$,得到序列$x''$。
于是:
$$\sum_{i=1}^{n}(x''_i-y_i)^2$$
$$=\sum_{i=1}^{n}(x'_i-y_i+c)^2$$
(假装后面的没有'的就当有吧,公式不知道为啥烂掉了)
$$=\sum_{i=1}^{n}x_i^2+y_i^2+c^2-2x_iy_i+2(x_i-y_i)c$$
$$=\sum_{i=1}^{n}x_i^2+y_i^2+c^2+(\sum_{i=1}^{n}(x_i-y_i))c-2x_iy_i$$
发现这是个关于$c$的二次函数再加上一坨$-2x'_iy_i$。
对于$c$只需要运用一下初中的数学知识即可。
具体地:
设$t=\sum_{i=1}^{n}x_i-y_i$.
则与$c$有关的式子是$nc^2+2tc$。
这个时候其实$-100$到$100$暴搜应该也可以的。
然后我们运用初中的数学配个方就可以快速算出$c$的取值,但是注意$c$为整数,所以我们就去周围几个数判几下就可以了。
对于后面的那个,只需要倍长$y$,翻转$x$,然后套路$FFT$即可。
具体地:
为了方便,下面把$x_i$和$y_i$下标看做从$0$开始。
首先化环为链,我们把$y$倍长。
然后构造多项式:
$$h_i=\sum_{j=0}^{n-1}x_jy_{i+j-1}$$
看起来可以用$FFT$来优化。
我们只需要翻转$x$数组,得到:
$$h_i=\sum_{j=0}^{n-1}x_{n-j-1}y_{i+j-1}$$
让$h_i$整体右移$n-1$位,再重新整理上式得:
$$h_i=\sum_{j=0}^{i}x_jy_{i-j}$$
显然这个可以$FFT$。
其中只有$h_{n-1}\dots h_{2n-2}$是有用的。
求出来之后,只要求下有效$h_i$的最大值$max$即可。然后让答案减掉$-2max$
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1<<18;
double PI=acos(-1.0);
int n,m,c,x[N],y[N],t=0;
int s,L,R[N];
LL ans=0,xymax=0;
struct C{
double r,i;
C(){}
C(double a,double b){r=a,i=b;}
C operator + (C x){return C(r+x.r,i+x.i);}
C operator - (C x){return C(r-x.r,i-x.i);}
C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
}w[N],A[N],B[N];
LL calc(LL c){
return c*c*n+c*t*2;
}
LL getc_val(int t,int n){
LL c1=-t/n,c2=c1+1,c3=c1-1;
return min(min(calc(c1),calc(c2)),calc(c3));
}
void FFT(C a[],int n){
for (int i=0;i<n;i++)
if (i<R[i])
swap(a[i],a[R[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=0;i<n;i++)
scanf("%d",&x[i]);
for (int i=0;i<n;i++)
scanf("%d",&y[i]),t+=x[i]-y[i],ans+=x[i]*x[i]+y[i]*y[i];
ans+=getc_val(t,n);
for (s=1,L=0;s<n*3;s<<=1,L++);
for (int i=0;i<s;i++){
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
w[i]=C(cos(2*i*PI/s),sin(2*i*PI/s));
A[i]=B[i]=C(0,0);
}
for (int i=0;i<n;i++)
A[i]=C(x[n-i-1],0),B[i]=B[i+n]=C(y[i],0);
FFT(A,s),FFT(B,s);
for (int i=0;i<s;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,s);
for (int i=n-1;i<2*n;i++)
xymax=max(xymax,(LL)(A[i].r/s+0.5));
ans-=xymax*2;
printf("%lld",ans);
return 0;
}
BZOJ4827 [Hnoi2017]礼物 多项式 FFT的更多相关文章
- [BZOJ4827][Hnoi2017]礼物(FFT)
4827: [Hnoi2017]礼物 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1315 Solved: 915[Submit][Status] ...
- [bzoj4827][Hnoi2017]礼物_FFT
礼物 bzoj-4827 Hnoi-2017 题目大意:给定两个长度为$n$的手环,第一个手环上的$n$个权值为$x_i$,第二个为$y_i$.现在我可以同时将所有的$x_i$同时加上自然数$c$.我 ...
- [HNOI2017] 礼物 - 多项式乘法FFT
题意:给定两个 \(n\) 元环,环上每个点有权值,分别为 \(x_i, y_i\).定义两个环的差值为 \[\sum_{i=0}^{n-1}{(x_i-y_i)^2}\] 可以旋转其中的一个环,或者 ...
- BZOJ4827: [Hnoi2017]礼物(FFT 二次函数)
题意 题目链接 Sol 越来越菜了..裸的FFT写了1h.. 思路比较简单,直接把 \(\sum (x_i - y_i + c)^2\) 拆开 发现能提出一坨东西,然后与c有关的部分是关于C的二次函数 ...
- BZOJ4827:[HNOI2017]礼物(FFT)
Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...
- 洛谷P3723 [AH2017/HNOI2017]礼物(FFT)
传送门 首先,两个数同时增加自然数值相当于只有其中一个数增加(此增加量可以小于0) 我们令$x$为当前的增加量,${a},{b}$分别为旋转后的两个数列,那么$$ans=\sum_{i=1}^n(a_ ...
- bzoj 4827: [HNOI2017]礼物 (FFT)
一道FFT 然而据说暴力可以水70分 然而我省选的时候看到了直接吓傻了 连暴力都没打 太弱了啊QAQ emmmm 详细的拆开就看其他题解吧233 最后那一步卷积其实我一直没明白 后来画画图终于懂了 ...
- bzoj4827 [Hnoi2017]礼物
Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...
- bzoj千题计划303:bzoj4827: [Hnoi2017]礼物
https://www.lydsy.com/JudgeOnline/problem.php?id=4827 式子化简一下,发现最后只跟 Σ xi*yi 有关 第二个序列反转,就可以用FFT优化 注意: ...
随机推荐
- Java集合:HashMap底层实现和原理(源码解析)
Note:文章的内容基于JDK1.7进行分析.1.8做的改动文章末尾进行讲解. 一.先来熟悉一下我们常用的HashMap: 1.概述 HashMap基于Map接口实现,元素以键值对的方式存储,并且允许 ...
- mysql如何直接查出从1开始递增的数
比如我的一个sql语句 SELECT nick_name FROM t_user ; 得到的结果是:张三李四王五 而现在我想要的结果是:1 张三2 李四3 王五 应该如何写sql呀? 答案就是用 @r ...
- springboot2.0整合es的异常总结
异常: availableProcessors is already set to [4], rejecting [4] 在启动类中加入 System.setProperty("es.set ...
- python之路day01--变量
一.变量 变量就是将一些运算的中间结果暂存到内存中,以便后续代码块调用. 规范: 1.必须由数字.字母.下划线任意组合,且不能数字开头. 2.不能是python中的关键字.如:‘print’ 'and ...
- Java基础 -- 复用类(组合和继承)
复用类有两种实现方式. 在新的类中产生现有类的对象,由于新的类是由现有类的对象所组成,所以这种方法称之为组合. 采用继承实现. 一 组合语法 下面创建两个类WaterSource和Sprinkler ...
- prometheus 基于文件的目标发现
prometheus 基于文件的目标发现 1.创建目录 cd /usr/local/prometheus/conf mkdir -pv targets/{nodes,docker} 2.修改prome ...
- 【C#】判断字符串中是否包含指定字符串,contains与indexof方法效率问题
#方法一:使用string.Contains方法 string.Contains是大小写敏感的,如果要用该方法来判断一个string是否包含某个关键字keyword,需要把这个string和这个key ...
- openstack项目【day24】:OpenStack mitaka部署
前言: openstack的部署非常简单,简单的前提建立在扎实的理论功底,本人一直觉得,玩技术一定是理论指导实践,网上遍布个种搭建方法都可以实现一个基本的私有云环境,但是诸位可曾发现,很多配置都是重复 ...
- ZooKeeper 概述
ZooKeeper:分布式应用程序的分布式协调服务 ZooKeeper:是用于分布式应用程序的分布式开源协调服务 可以简单理解:ZooKeeper = 文件系统 + 通知机制 从设计模式角度理解:Zo ...
- idea设置java内存
-Xms1024m -Xmx10240m -XX:MaxPermSize=512m 设置环境变量JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSi ...