Description
Input
Output
Sample Input
1 2 3 4 5
6 3 3 4 5
Sample Output
HINT
【样例解释】
需要将第一个手环的亮度增加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。
题解
我们假设第二个手环偏移量为 $p$ ,第二个手环增加的亮度为 $c$ 。由于两个手环亮度均可修改,如果第一个手环增加亮度为 $c$ 就相当于第二个手环减小的亮度为 $c$ 。一个容易得到的结论就是: $|c|\leq m$ 。在此基础上,我们要求的就是 $$\min_{\begin{aligned}0\leq p<n~~\\-m\leq c\leq m\end{aligned}}\sum_{i=0}^{n-1}(x_i-y_{(i+p)mod~n}-c)^2$$
将求和式拆开,我们得到 $$\sum_{i=0}^{n-1}(x_i^2+y_i^2+c^2+2y_ic-2x_ic)-2\sum_{i=0}^{n-1}x_iy_{(i+p)mod~n}$$
注意到前面那个求和式与偏移量 $p$ 是没有关系的,后面的求和式是和亮度增量 $c$ 是没有关系的。我们可以求出前式的最小值,与后式的最大值,作差即为答案。前式的最小值很好求,我们只要在 $c$ 的范围内枚举亮度增量即可。而后面这个式子比较麻烦。
对于式子 $\sum\limits_{i=0}^{n-1}x_iy_{(i+p)mod~n}$ 我们试着将第二个手环翻转,即 $y_{-i}=y_i\pmod{n}$ ,那么现在: $\sum\limits_{i=0}^{n-1}x_iy_{(-i+p)mod~n}=\sum\limits_{i=0}^{p}x_iy_{-i+p}+\sum\limits_{i=p+1}^{n-1}x_iy_{-i+p+n}$ 。这玩意不就是多项式卷积的第 $p$ 项和第 $p+n$ 项的系数么。卷积完枚举 $p$ 求个最小值就好了,美滋滋。
1 //It is made by Awson on 2018.1.27 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <complex> 14 #include <iostream> 15 #include <algorithm> 16 #define LL long long 17 #define dob complex<double> 18 #define Abs(a) ((a) < 0 ? (-(a)) : (a)) 19 #define Max(a, b) ((a) > (b) ? (a) : (b)) 20 #define Min(a, b) ((a) < (b) ? (a) : (b)) 21 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 22 #define writeln(x) (write(x), putchar(‘\n‘)) 23 #define lowbit(x) ((x)&(-(x))) 24 using namespace std; 25 const int INF = ~0u>>1; 26 const double pi = acos(-1.0); 27 const int N = 5e4*4; 28 void read(int &x) { 29 char ch; bool flag = 0; 30 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == ‘-‘)) || 1); ch = getchar()); 31 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 32 x *= 1-2*flag; 33 } 34 void write(int x) { 35 if (x > 9) write(x/10); 36 putchar(x%10+48); 37 } 38 39 int n, m, x, L, R[N+5], tol, tolx, toly, s, c, tolxy, ans = INF; 40 dob a[N+5], b[N+5]; 41 42 void FFT(dob *A, int o) { 43 for (int i = 0; i < n; i++) if (i > R[i]) swap(A[i], A[R[i]]); 44 for (int i = 1; i < n; i <<= 1) { 45 dob wn(cos(pi/i), sin(pi*o/i)), x, y; 46 for (int j = 0; j < n; j += (i<<1)) { 47 dob w(1, 0); 48 for (int k = 0; k < i; k++, w *= wn) { 49 x = A[j+k], y = w*A[j+i+k]; 50 A[j+k] = x+y, A[i+j+k] = x-y; 51 } 52 } 53 } 54 } 55 void work() { 56 read(n), read(c); s = n; n--; 57 for (int i = 0; i <= n; i++) read(x), a[i] = x, tol += x*x, tolx -= x; 58 for (int i = n; i >= 0; i--) read(x), b[i] = x, tol += x*x, tolx += x; 59 m = 2*n; 60 for (n = 1; n <= m; n <<= 1) L++; 61 for (int i = 0; i < n; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1)); 62 FFT(a, 1), FFT(b, 1); 63 for (int i = 0; i <= n; i++) a[i] *= b[i]; 64 FFT(a, -1); 65 for (int i = 0; i < s; i++) x = int(a[i].real()/n+0.5)+int(a[i+s].real()/n+0.5), tolxy = Max(tolxy, x); 66 for (int i = -c; i <= c; i++) x = tol+tolx*2*i+i*i*s-2*tolxy, ans = Min(ans, x); 67 writeln(ans); 68 } 69 int main() { 70 work(); 71 return 0; 72 }