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$只需要运用一下初中的数学知识即可。

  对于后面的那个,只需要倍长$y$,翻转$x$,然后套路$FFT$即可。

  (有空再仔细写吧,可以先参照我的其他$FFT$题解中的套路做法)

代码

#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;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/8823962.html

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

BZOJ4827 [Hnoi2017]礼物 多项式 FFT的相关文章

[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$. 想法: 水题啊..... 推推式子,我们假设就加了$

BZOJ4827: [Hnoi2017]礼物

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

bzoj 4827: [HNOI2017]礼物 (FFT)

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

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

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

【bzoj4827】[Hnoi2017]礼物 FFT

题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 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:[AH2017/HNOI2017]礼物——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=4827 https://www.luogu.org/problemnew/show/P3723 题面见原题. 参考了洛谷一些题解. 先推式子,x数组为a,y数组为b,将b数组倍长后有: 因为c的范围在[-m,m]之间,而m=100,且稍加思考后发现k在1,3,4项中是无用的,所以通过枚举c取得1,3,4项和的最小值. 考虑计算第二项,其实是卷积型,实际上将a数组前移并倒转即可得到: 变成了卷积,F

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

CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT

原文链接http://www.cnblogs.com/zhouzhendong/p/8835443.html 题目传送门 - CodeForces 958F3 题意 有$n$个球,球有$m$种颜色,分别编号为$1\cdots m$,现在让你从中拿$k$个球,问拿到的球的颜色所构成的可重集合有多少种不同的可能. 注意同种颜色球是等价的,但是两个颜色为$x$的球不等价于一个. $1\leq n\leq 2\times 10^5,\ \ \ \ \ 1\leq m,k\leq n$. 题解 来自Hel