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。
solutionsolutionsolution:
比较简单的一道题
没有改变亮度就是sbsbsb题
考虑加上这个亮度
(x+c−y)2=x2+c2+2xc+y2−2xy−2yc(x+c-y)^2=x^2+c^2+2xc+y^2-2xy-2yc(x+c−y)2=x2+c2+2xc+y2−2xy−2yc
=x2+y2−2xy+c2+2c(x−y)=x^2+y^2-2xy+c^2+2c(x-y)=x2+y2−2xy+c2+2c(x−y)
很显然我们可以把两个放到生成函数中,把第二个手环倍长+翻转,考虑怎么算答案
我们显然是要上面某个对应位置上面的值最小
显然x2+y2x^2+y^2x2+y2可以不用考虑,这个式子的和是恒定的
带ccc的项很棘手,我们从二次函数的角度考虑,假如我把ccc留着,得到式子后我们显然可以通过二次函数可以找到最优的ccc的取值
观察可以发现不论是怎么安排第二个手环的位置,都有a=n,b=∑(x−y)a=n,b=\sum(x-y)a=n,b=∑(x−y)
也就是说ccc的取值是确定的
那么式子中不确定的只有−2xy-2xy−2xy了
我们只要让它最小就行了。
直接卷积
复杂度O(nlogn)O(nlogn)O(nlogn)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
int rd()
{
int num = 0;char c = getchar();bool flag = true;
while(c < '0'||c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') num = num*10+c-48,c = getchar();
if(flag) return num;else return -num;
}
int r[401000],n,m;
struct comp{
double x,y;
comp(double x_=0,double y_=0) {x=x_;y=y_;}
inline comp operator + (const comp& a){return comp(x+a.x,y+a.y);}
inline comp operator - (const comp& a){return comp(x-a.x,y-a.y);}
inline comp operator * (const comp& a){return comp(x*a.x-y*a.y,x*a.y+y*a.x);}
}a[401000],b[401000],w[401000];
const double pi = acos(-1.0);
int fft(comp *a,int flen,int f)
{
w[0] = comp(1,0);
rep(i,0,flen-1) if(i<r[i]) swap(a[i],a[r[i]]);
for(int len=2;len<=flen;len<<=1)
{
comp wn = comp( cos(pi*2/len) , 1.0*f*sin(pi*2/len) );
rep(i,1,len/2) w[i] = w[i-1]*wn;
for(int st=0;st<flen;st+=len)
rep(i,0,len/2-1)
{
comp x = a[st+i],y = a[st+len/2+i]*w[i];
a[st+i] = x+y;
a[st+len/2+i] = x-y;
}
}
}
int c[401000],ans,sigma,tp;
inline int sqr(int x){return x*x;}
int main()
{
n = rd();m = rd();
rep(i,0,n-1) a[i].x = (double)rd(),ans += sqr((int)a[i].x),sigma -= (int)a[i].x;
rep(i,0,n-1) b[i].x = (double)rd(),ans += sqr((int)b[i].x),sigma += (int)b[i].x;
reverse(b,b+n);
rep(i,0,n-1) b[i+n] = b[i];
int flen = 1;
while(flen < 3*n-1) flen *= 2;
rep(i,n,flen-1) a[i] = comp(0,0);
rep(i,2*n,flen-1) b[i] = comp(0,0);
rep(i,0,flen-1) r[i] = (r[i>>1]>>1) | ((i&1)?flen/2:0);
fft(a,flen,1);fft(b,flen,1);
rep(i,0,flen-1) a[i] = a[i] * b[i];
fft(a,flen,-1);
rep(i,0,flen-1) c[i] = (int)(a[i].x/flen+0.5);
int mx = 0;
rep(i,n-1,2*n-2) mx = max(mx,2*c[i]);
mx = -mx; ans += mx;
double bz = 1.0*sigma/n;
if(abs(bz)>=m) tp = bz>0?m:-m;
else
{
tp = (int)bz;
int det1 = tp*tp*n-2*tp*sigma;
tp++;
if(tp*tp*n-2*tp*sigma > det1) tp--;
}
ans += tp*tp*n-2*tp*sigma;
printf("%d\n",ans);
return 0;
}