Description
我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n,其中 n 为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手 环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释): ∑i=1n(xi−yi)2\sum_{i=1}^{n}(x_i-y_i)^2∑i=1n(xi−yi)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
solution
虽然题目说只能增加自然数ccc亮度
但是既可以是给第一个环加,也可以是给第二个环加
所以转化为给固定一个环增加ccc亮度,ccc可以是负数
假设枚举AAA环增加的亮度为xxx,考虑最后的结果
∑i=1n(ai+x−bi)2=∑i=1n(ai2+x2+bi2+2aix−2aibi−2bix)\sum_{i=1}^n(a_i+x-b_i)^2=\sum_{i=1}^n(a_i^2+x^2+b_i^2+2a_ix-2a_ib_i-2b_ix)i=1∑n(ai+x−bi)2=i=1∑n(ai2+x2+bi2+2aix−2aibi−2bix)=∑i=1nai2+∑i=1nbi2+nx2+2x∑i=1nai−2x∑i=1nbi−2∑i=1naibi=\sum_{i=1}^na_i^2+\sum_{i=1}^nb_i^2+nx^2+2x\sum_{i=1}^na_i-2x\sum_{i=1}^nb_i-2\sum_{i=1}^na_ib_i=i=1∑nai2+i=1∑nbi2+nx2+2xi=1∑nai−2xi=1∑nbi−2i=1∑naibi
发现只有最后一项2∑i=1naibi2\sum_{i=1}^na_ib_i2∑i=1naibi可以改变
因为环可以旋转,那么对应位的亮度乘积求和可能会不同
所以最大化该项就可以保证差异值最小
h(i)=∑j=0if(i)∗g(i−j)h(i)=\sum_{j=0}^if(i)*g(i-j)h(i)=j=0∑if(i)∗g(i−j)
将AAA环扩倍,反转BBB环
使用FFTFFTFFT卷积,这样AAA环的(n,2n](n,2n](n,2n]就是所有可能旋转的情况
code
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 300005
#define ll long long
struct complex {
double x, i;
complex(){}
complex( double X, double I ) {
x = X, i = I;
}
}A[maxn], B[maxn], rB[maxn];
double pi = acos( -1.0 );
complex operator + ( complex a, complex b ) {
return complex( a.x + b.x, a.i + b.i );
}
complex operator - ( complex a, complex b ) {
return complex( a.x - b.x, a.i - b.i );
}
complex operator * ( complex a, complex b ) {
return complex( a.x * b.x - a.i * b.i, a.x * b.i + a.i * b.x );
}
int len = 1;
int r[maxn];
void FFT( complex *c, int f ) {
for( int i = 0;i < len;i ++ )
if( i < r[i] ) swap( c[i], c[r[i]] );
for( int i = 1;i < len;i <<= 1 ) {
complex omega( cos( pi / i ), f * sin( pi / i ) );
for( int j = 0;j < len;j += ( i << 1 ) ) {
complex w( 1, 0 );
for( int k = 0;k < i;k ++, w = w * omega ) {
complex x = c[j + k], y = w * c[j + k + i];
c[j + k] = x + y;
c[j + k + i] = x - y;
}
}
}
}
ll suma1, suma2, sumb1, sumb2;
int n, m;
int main() {
scanf( "%d %d", &n, &m );
for( int i = 1;i <= n;i ++ ) {
scanf( "%lf", &A[i].x );
A[i + n].x = A[i].x;
suma1 += A[i].x;
suma2 += A[i].x * A[i].x;
}
for( int i = 1;i <= n;i ++ ) {
scanf( "%lf", &B[i].x );
sumb1 += B[i].x;
sumb2 += B[i].x * B[i].x;
}
for( int i = 1;i <= n;i ++ )
rB[i].x = B[n - i + 1].x;
int l = 0;
while( len <= n * 3 ) {
len <<= 1;
l ++;
}
for( int i = 0;i < len;i ++ )
r[i] = ( r[i >> 1] >> 1 ) | ( ( i & 1 ) << ( l - 1 ) );
FFT( A, 1 );
FFT( rB, 1 );
for( int i = 0;i <= len;i ++ )
A[i] = A[i] * rB[i];
FFT( A, -1 );
for( int i = 0;i <= len;i ++ )
A[i].x = ( ll ) ( A[i].x / len + 0.5 );
ll ans = 1ll << 60;
for( int i = 1;i <= n;i ++ )
for( int j = -m;j <= m;j ++ ) //初始的亮度都不超过m 那么就没必要把差x弄得太过火
ans = min( ans, suma2 + sumb2 + n * j * j + 2ll * j * ( suma1 - sumb1 ) - 2ll * ( ll ) A[i + n].x );
printf( "%lld", ans );
return 0;
}
/*
Σ(ai+x-bi)^2=Σai^2+Σbi^2+n*x*x+2*x*(Σai-Σbi)-2*Σai*bi
因为旋转,所以最后一项是不固定的
在枚举x后最大化后面一项
最后的相差就是最小的
考虑卷积
*/
本文详细介绍了如何解决一个关于情侣手环亮度调整的问题,旨在最小化两个手环之间的亮度差异。通过数学分析和使用FFT快速傅里叶变换,找到了在允许手环旋转和调整亮度的情况下,使差异值达到最小的策略。具体方法包括将问题转化为寻找最佳亮度增益,利用环形结构的最大化乘积和,并通过卷积计算找到最优解。
1527

被折叠的 条评论
为什么被折叠?



