让你求(a[i] - b[(i + x) % n]) ^ 2的最大值,其中x从0到n-1。
因为结果总是sum(a[i] ^ 2) + sum(b[i] ^ 2) - sum(2 * a[i] * b[(i + x) % n])。
因此只需要找到最小的sum(2 * a[i] * b[(i + x) % n])即可。
据此我们构造两个向量。
a = (a[n - 1], a[n - 2], ... , a[1], a[0], a[n - 1], a[n - 2], ... , a[2], a[1])
b = (b[0], b[1], ... , b[n - 2], b[n - 1])
可以看出要求sum的最小值就是求a与b的卷积从n-1到2 * n - 2的最小值(下标从0开始)。
因此用fft可以求出卷积,再找一遍最小值,记住偏移量,根据偏移量计算结果就ok
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <string> #include <cmath> using namespace std; const int maxn = 240005; const double PI = acos(-1.0); struct Complex { double x, y; Complex(double x = 0, double y = 0) : x(x), y(y) { } Complex operator + (const Complex &rhs) { return Complex(x + rhs.x, y + rhs.y); } Complex operator - (const Complex &rhs) { return Complex(x - rhs.x, y - rhs.y); } Complex operator * (const Complex &rhs) { return Complex(x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x); } }a[maxn], b[maxn]; long long num1[maxn], num2[maxn]; void change(Complex y[], int len) { int i, j, k; for(i = 1, j = len / 2; i < len - 1; ++i) { if(i < j) swap(y[i], y[j]); k = len / 2; while(j >= k) { j -= k; k /= 2; } if(j < k) j += k; } } void fft(Complex y[], int len, int on) { change(y, len); for(int h = 2; h <= len; h <<= 1) { Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h)); for(int j = 0; j < len; j += h) { Complex w(1, 0); for(int k = j; k < j + h / 2; ++k) { Complex u = y[k]; Complex t = w * y[k + h / 2]; y[k] = u + t; y[k + h / 2] = u - t; w = w * wn; } } } if(on == -1) for(int i = 0; i < len; ++i) y[i].x /= len; } int main() { int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); for(int i = 0; i < n; ++i) { scanf("%lld", &num1[i]); a[n - i - 1].x = num1[i]; a[n - i - 1].y = 0; } for(int i = n; i < 2 * n - 1; ++i) { a[i].x = a[i - n].x; a[i].y = 0; } for(int i = 0; i < n; ++i) { scanf("%lld", &num2[i]); b[i].x = num2[i]; b[i].y = 0; } int tmp = 1; while(tmp < 2 * n - 1) tmp <<= 1; for(int i = 2 * n - 1; i < tmp; ++i) { a[i].x = a[i].y = 0; } for(int i = n; i < tmp; ++i) { b[i].x = b[i].y = 0; } fft(a, tmp, 1); fft(b, tmp, 1); for(int i = 0; i < tmp; ++i) a[i] = a[i] * b[i]; fft(a, tmp, -1); double MAX = -1; int pos = -1; for(int i = n - 1; i < 2 * n - 1; ++i) { if(a[i].x > MAX) { MAX = a[i].x; pos = i; } } pos = pos - n + 1; long long ans = 0; for(int i = 0; i < n; ++i) { ans += (num1[i] - num2[(i + pos) % n]) * (num1[i] - num2[(i + pos) % n]); } printf("%lld\n", ans); } return 0; }
时间: 2024-10-13 18:47:07