洛谷3723 [AH2017/HNOI2017]礼物
2018-02-26 15:05
274 查看
标签:FFT
但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号1,2,…,n,其中 n 为每个手环的装饰物个数, 第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释):
∑i=1n(xi−yi)2∑i=1n(xi−yi)2
麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?
接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时针方向上各装饰物的亮度。
可以大于 m。
旋转一下第二个手环。对于该样例,是将第二个手环的亮度6 3 3 4 5向左循环移动一个位置,使得第二手环的最终的亮度为: 3 3 4 5 6。
此时两个手环的亮度差异值为1
70%的数据满足n≤5000;
100%的数据满足1≤n≤50000, 1≤m≤100, 1≤ai≤m。
先O(n^2)查找旋转的最优位置
然后O(n*m)查找最优的整体增减
那么复杂度瓶颈就在于查找旋转的最优位置
正解就开始推式子了
ans=min(∑i=1n(Xi+C−Y(i+p)%n)2)ans=min(∑i=1n(Xi+C−Y(i+p)%n)2)
然后平方展开,得到
ans=min(∑i=1n−2XiY(i+p)%n+∑i=1n((Xi+C)2−2∗C∗Y(i+p)%n+Y2(i+p)%n))ans=min(∑i=1n−2XiY(i+p)%n+∑i=1n((Xi+C)2−2∗C∗Y(i+p)%n+Y(i+p)%n2))
对于前一个Σ求和,可以将x反转
∑i=1n−2Xn−i+1Y(i+p)%n∑i=1n−2Xn−i+1Y(i+p)%n
这个式子可以通过FFT求
后面的Σ求和,可以O(n*m)处理
正解代码
题目
题目传送门题目描述
我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号1,2,…,n,其中 n 为每个手环的装饰物个数, 第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释):
∑i=1n(xi−yi)2∑i=1n(xi−yi)2
麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?
输入输出格式
输入格式
输入数据的第一行有两个数n, m,代表每条手环的装饰物的数量为n,每个装饰物的初始亮度小于等于m。接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时针方向上各装饰物的亮度。
输出格式
输出一个数,表示两个手环能产生的最小差异值。注意在将手环改造之后,装饰物的亮度可以大于 m。
输入输出样例
输入样例#1
5 6 1 2 3 4 5 6 3 3 4 5
输出样例#1
1
说明
样例解释
需要将第一个手环的亮度增加1,第一个手环的亮度变为: 2 3 4 5 6旋转一下第二个手环。对于该样例,是将第二个手环的亮度6 3 3 4 5向左循环移动一个位置,使得第二手环的最终的亮度为: 3 3 4 5 6。
此时两个手环的亮度差异值为1
数据范围
30%的数据满足n≤500, m≤10;70%的数据满足n≤5000;
100%的数据满足1≤n≤50000, 1≤m≤100, 1≤ai≤m。
题意
给定序列x,y,可以使x序列旋转或者整体增减,求min∑i=1n(xi−yi)2min∑i=1n(xi−yi)2分析
70分很好想到先O(n^2)查找旋转的最优位置
然后O(n*m)查找最优的整体增减
那么复杂度瓶颈就在于查找旋转的最优位置
正解就开始推式子了
ans=min(∑i=1n(Xi+C−Y(i+p)%n)2)ans=min(∑i=1n(Xi+C−Y(i+p)%n)2)
然后平方展开,得到
ans=min(∑i=1n−2XiY(i+p)%n+∑i=1n((Xi+C)2−2∗C∗Y(i+p)%n+Y2(i+p)%n))ans=min(∑i=1n−2XiY(i+p)%n+∑i=1n((Xi+C)2−2∗C∗Y(i+p)%n+Y(i+p)%n2))
对于前一个Σ求和,可以将x反转
∑i=1n−2Xn−i+1Y(i+p)%n∑i=1n−2Xn−i+1Y(i+p)%n
这个式子可以通过FFT求
后面的Σ求和,可以O(n*m)处理
code
70分暴力代码#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) #define ll long long #define mem(x,num) memset(x,num,sizeof x) #define reg(x) for(int i=last[x];i;i=e[i].next) #define inf 1e18 using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=1e5+6; int n,m,x[maxn],y[maxn],pos; ll sum,ans,Min=inf; int main() { n=read(),m=read(); rep(i,1,n)x[i+n]=x[i]=read(); rep(i,1,n)y[i+n]=y[i]=read(); rep(i,1,n){ sum=0; rep(j,i,i+n-1)sum+=(x[j]-y[j-i+1])*(x[j]-y[j-i+1]); if(sum<Min)Min=sum,pos=i; } ans=Min; rep(c,1,m){ sum=0; rep(j,pos,pos+n-1)sum+=(x[j]+c-y[j-pos+1])*(x[j]+c-y[j-pos+1]); ans=min(sum,ans);sum=0; rep(j,pos,pos+n-1)sum+=(x[j]-y[j-pos+1]-c)*(x[j]-y[j-pos+1]-c); ans=min(sum,ans); } cout<<ans<<endl; return 0; }
正解代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<complex> #define rep(i,a,b) for(ll i=a;i<=b;i++) #define dep(i,a,b) for(ll i=a;i>=b;i--) #define ll long long #define mem(x,num) memset(x,num,sizeof x) #define reg(x) for(int i=last[x];i;i=e[i].next) using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } typedef complex<double> E; const int maxn=5e4+6; double pi=acos(-1.0); E A[maxn<<3],B[maxn<<3],c[maxn<<3]; double x[maxn<<3],y[maxn<<3]; ll ans1,ans2,sum1,sum2,ans,ans3; int len,n,m,R[maxn<<3],lg; void fft(E *a,int f){ rep(i,0,len-1) if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<len;i<<=1){ E wn(cos(pi/i),f*sin(pi/i)); for(int j=0;j<len;j+=(i<<1)){ E w(1.0,0); for(int k=0;k<i;k++,w*=wn){ E x=a[j+k],y=w*a[j+k+i]; a[j+k]=x+y; a[j+k+i]=x-y; } } } } int main() { n=read(),m=read(); rep(i,1,n){ scanf("%lf",&x[i]); ans1+=x[i]*x[i]; sum1+=x[i]; } rep(i,1,n){ scanf("%lf",&y[i]); ans1+=y[i]*y[i]; sum2+=y[i]; y[i+n]=y[i]; } rep(i,1,n)A[i]=x[n-i+1]; rep(i,1,2*n)B[i]=y[i]; len=1;while(len<4*n)len*=2,lg++; rep(i,0,len)R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1)); fft(A,1),fft(B,1); rep(i,0,len-1)c[i]=A[i]*B[i]; fft(c,-1); ans=1e9; rep(i,-m,m){ ans2=ans1; ans2+=2*i*sum1;ans2-=2*i*sum2; ans2+=n*i*i; rep(j,0,n-1){ ans3=ans2; ans3-=2*(ll)(c[n+j+1].real()/len+0.5); ans=min(ans,ans3); } } printf("%lld\n",ans); }
相关文章推荐
- luogu3723 [AH2017/HNOI2017]礼物 【NTT】
- BZOJ4827:[AH2017/HNOI2017]礼物——题解
- [AH2017/HNOI2017]礼物
- [AH2017/HNOI2017]礼物
- 给自己的礼物-谁是谁的麦琪?
- 吃了蛋糕,收了礼物 ^_^,大学里最后的生日到了~
- 一件礼物
- 给c++程序员的一份礼物——常用工具集
- 上帝怎么给你礼物
- 给c++程序员的一份礼物——常用工具集(转)
- 圣诞节送给妈妈的礼物
- 校内网:今冬元旦流行虚拟礼物风图
- 平安夜的礼物!Geforce8系列 CI/QE 终于搞定了!支持8800 8600 8500 8400 ....
- 全国各地土特产一览表(以后好问朋友要礼物了)
- 谷歌员工年终礼物——现金变手机
- 来自matrix67的礼物:《C++语言程序设计》无主题书雕
- 礼物=垃圾?一个幼儿园教师的无耻行为
- 送给老婆的两周年小礼物
- 阳光下:平凡的人,平常的礼物
- 今天收到51CTO发送的礼物咯~