首页 > 其他分享 >[AHOI2017/HNOI2017]礼物

[AHOI2017/HNOI2017]礼物

时间:2022-12-14 21:45:52浏览次数:62  
标签:node 200001 return int AHOI2017 sum times HNOI2017 礼物

链接:https://www.luogu.com.cn/problem/P3723

题目描述:给定两个序列,每次可以旋转其中的一个或给其中一个加上一个数\(c\),求两个序列对应位置的差的平方和所能达到的最小值。

题解:

\(\sum_{i=1}^{n}(x_{i}-y_{i}+c)^2\)

\(=\sum_{i=1}^{n}(x_{i}^2-2\times x_{i}\times y_{i}+y_{i}^2+c^2+c\times(x_{i}-y_{i}))\)

可以先求出\(c^2+c\times\sum_{i=1}^{n}(x_{i}-y_{i})\)的最小值, 这个可以利用二次函数顶点公式去求。

当然,还有旋转的操作,我们发现旋转操作只会影响\(2\times x_{i}\times y_{i}\)这一项,我们考虑求出顺时针旋转\(t\)次时\(2\times x_{i}\times y_{i}\)这一项的贡献。

我们可以得到旋转\(t\)次的答案为\(\sum_{i=1}^{n}2\times x_{i}\times y_{i+t}\)(当然,\(i+t>n\)时要化做\(i+t-n\))

令\(f_{i}=x_{n-i}\),则答案可化作\(\sum_{i=1}^{n}2\times x_{n-i}\times y_{i+t}\)。

可以发现这是一个卷积的形式,跑\(fft\)即可。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct node
{
	double x,y;
};
int n,m;
node tmp,w,wn,A[200001],B[200001],C[200001];
long long sum,res,X[200001],Y[200001],maxn;
const double Pi=asin(1)*2;
double c;
node make_node(double x,double y)
{
	tmp.x=x;
	tmp.y=y;
	return tmp;
}
node operator + (node x,node y)
{
	return make_node(x.x+y.x,x.y+y.y);
}
node operator - (node x,node y)
{
	return make_node(x.x-y.x,x.y-y.y);
}
node operator * (node x,node y)
{
	return make_node(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);
} 
void FFT(int limit,node *a,int type)
{
	if (limit==1)
		return;
	node a2[limit/2+1],b2[limit/2+1];
	for (int i=0;i<limit;i+=2)
	{
		a2[i/2]=a[i];
		b2[i/2]=a[i+1];
	}
	FFT(limit/2,a2,type);
	FFT(limit/2,b2,type);
	wn=make_node(1,0),w=make_node(cos(2*Pi/limit),type*sin(2*Pi/limit));
	for (int i=0;i<limit/2;++i,wn=wn*w)
	{
		a[i]=a2[i]+b2[i]*wn;
		a[i+limit/2]=a2[i]-b2[i]*wn;
	}
	return;
}
int main()
{
	int limit=1;
	cin>>n>>m;
	for (int i=1;i<=n;++i)
		cin>>X[i];
	for (int i=1;i<=n;++i)
		cin>>Y[i]; 
	for (int i=1;i<=n;++i)
	{
		c+=(Y[i]-X[i])*1.0/n;
		sum+=X[i]-Y[i];
		res+=X[i]*X[i]+Y[i]*Y[i];
	}
	long long c1=floor(c),c2=ceil(c);
	res+=min(c1*c1*n+2*c1*sum,c2*c2*n+2*c2*sum);
	for (int i=0;i<=n;++i)
		A[n-i].x=X[i];
	for (int i=1;i<=n;++i)
		B[i].x=Y[i];
	while (limit<=2*n)
		limit*=2;
	FFT(limit,A,1);
	FFT(limit,B,1);
	for (int i=0;i<=limit;++i)
		C[i]=A[i]*B[i];
	FFT(limit,C,-1);
	for (int i=0;i<=n-1;++i)
		maxn=max(maxn,(long long)(C[i].x/limit+0.5)+(long long)(C[i+n].x/limit+0.5));
	cout<<res-2*maxn<<endl;
	return 0;
}

标签:node,200001,return,int,AHOI2017,sum,times,HNOI2017,礼物
From: https://www.cnblogs.com/zhouhuanyi/p/16983669.html

相关文章

  • [AHOI2017/HNOI2017]礼物
    链接:https://www.luogu.com.cn/problem/P3723题目描述:给定两个序列,每次可以旋转其中的一个或给其中一个加上一个数$c$,求两个序列对应位置的差的平方和所能达到的最小值。......
  • 富而喜悦一年一渡特别的礼物新年主题活动等你来参与!
    每一位摆渡人,都值得被记录,更值得被感谢。因此,我们为全天下的摆渡人打造了一个盛大的庆祝节日——富而喜悦旗下品牌新年主题活动:2023一年一渡特别的礼物!如果,你认同生命是一......
  • 致谢每一位ChunJun Contributor!这里有一份礼物等你领取!
    作为一个批流统一的数据集成框架,秉承着易用、稳定、高效的目标,ChunJun于2018年4月29日在Github上将内核源码正式开放。从还被叫作FlinkX,写下第一行代码开始,ChunJun已经走......
  • 163. 生日礼物
    题目链接163.生日礼物翰翰\(18\)岁生日的时候,达达给她看了一个神奇的序列\(A_1,A_2,…,A_N\)。她被允许从中选择不超过\(M\)个连续的部分作为自己的生日礼物。......
  • 教师节,收到学生的礼物和祝福,开心
    教师节,今天满课,早上上到晚上。有学生送了祝福,并说有礼物送我。我赶紧说不要,学生说,是一个盆花,放办公室的。很开心,是上学期上我课的学生,虽然今后我没机会上他们的课了,但他们......
  • P1194 买礼物
    ​​传送门​​思路:需要标记哪些通过优惠已经购买了,如果至少有一次是通过优惠购买的,则需要在答案上加上a,因为第一次不是通过优惠购买的。#include<bits/stdc++.h>usingname......
  • 【HNOI2017】礼物(FFT)
    显然,\(y_i\)加上\(c\)可以看成是\(x_i\)减去\(c\)。所以就变成了\(x_i\)加上一个整数(可正可负)。现将\(x\)环拆成一个长度为\(2n\)的序列\(a\)(复制一遍),把\(......
  • Python | 用Python制作送给女票的生日礼物
    HappyBirthday程序视频地址:​​https://www.bilibili.com/video/BV1R7411C7A1​​代码地址:​​https://github.com/borninfreedom/HappyBirthday​​截图: ......
  • P1194 买礼物
    P1194买礼物普及的题目,而且一眼就能看出该用什么做法。我主要是决定这道题建图的思想值得借鉴,每样东西原本的价格是a,所以新建一个节点0,0向i连边,边权为a,这样一共就有b......
  • 送爸妈最好的礼物,让爱与孝心一起归家
    还记得去年春节有一位儿子因为为父母手绘了一本“微信使用说明书”而感动了无数网友吗?他用自己的绘画特长,为父母专门手绘了一本“微信使用说明书”,几页图画配发详尽的文字,教......