先枚举 (c) 打一个表,然后发现这是个关于 (c) 的凸函数。
int main() {
read(n); read(m);
for (int i=1; i<=n; i++) read(A[i]);
for (int i=1; i<=n; i++) read(B[i]);
for (int j=-10; j<=10; j++) {
for (int i=1; i<=n; i++) A[i]+=j;
int mn=inf;
for (int k=0; k<n; k++) {
int cnt=0;
for (int i=1; i<=n; i++) {
int nxt=(i+k)%n;
if (nxt==0) nxt=n;
cnt+=(A[nxt]-B[i])*(A[nxt]-B[i]);
}
mn=min(mn, cnt);
}
printf("%d
", mn);
for (int i=1; i<=n; i++) A[i]-=j;
}
return 0;
}
输出的是:
628
521
424
337
260
193
136
89
52
25
8
1
4
17
40
73
116
169
232
305
388
于是考虑三分一个 (c),然后枚举那个移位,因为 (cin[-m,m]) 所以也不需要三分。
考虑拆式子:((a+c-b)^2=a^2+b^2+c^2+2ac-2bc-2ab)。然后只有 (2ab) 不是定值,于是只用求 (2ab) 的最大值即可。然后我们发现是 (sum A_{i+k} imes B_{i}),令 (ar{B_i}=B_{n-i+1}),然后就是个卷积式,所以最后移 (k) 位的答案就是卷起来后 ([x^{n+k+1}]),于是就做完了。
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-6;
const double pi=acos(-1.0);
const int MAXN=1000005;
const int inf=1e9;
template <typename T>
void read(T &x) {
T flag=1;
char ch=getchar();
for (; '0'>ch||ch>'9'; ch=getchar()) if (ch=='-') flag=-1;
for (x=0; '0'<=ch&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
x*=flag;
}
struct com{
double x, y;
com(){};
com(double _x, double _y) { x=_x, y=_y; }
friend com operator + (com u, com v) { return com(u.x+v.x, u.y+v.y); }
friend com operator - (com u, com v) { return com(u.x-v.x, u.y-v.y); }
friend com operator * (com u, com v) { return com(u.x*v.x-u.y*v.y, u.x*v.y+u.y*v.x); }
friend com operator * (com u, double v) { return com(u.x*v, u.y*v); }
friend com operator / (com u, double v) { return com(u.x/v, u.y/v); }
};
int n, m;
int A[100005], B[100005];
int rev[MAXN];
com F[MAXN], G[MAXN];
void fft(com*f, int n, int op) {
int len=(1<<n);
for (int i=0; i<len; i++) if (i<rev[i]) swap(f[i], f[rev[i]]);
for (int i=1; i<len; i<<=1) {
com wn1=com(cos(1.0*pi/i), 1.0*op*sin(1.0*pi/i));
for (int j=0; j<len; j+=(i<<1)) {
com wnk=com(1, 0);
for (int k=0; k<i; k++) {
com x=f[j+k], y=f[j+k+i]*wnk;
f[j+k]=x+y;
f[j+k+i]=x-y;
wnk=wnk*wn1;
}
}
}
if (op==-1) for (int i=0; i<len; i++) f[i]=f[i]/(1.0*len);
}
void poly_mul(com *f, com *g, int n, int m) {
int len=1, lg=0;
while (len<=n+m) len<<=1, lg++;
for (int i=0; i<MAXN; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
fft(f, lg, 1); fft(g, lg, 1);
for (int i=0; i<len; i++) f[i]=f[i]*g[i];
fft(f, lg, -1);
}
int main() {
int ans=0;
read(n); read(m);
int sum1=0, sum2=0;
for (int i=1; i<=n; i++) read(A[i]), ans+=A[i]*A[i], sum1+=A[i];
for (int i=1; i<=n; i++) read(B[i]), ans+=B[i]*B[i], sum2+=B[i];
for (int i=1; i<=n; i++) A[i+n]=A[i];
for (int i=1; i<=(n<<1); i++) F[i].x=A[i];
for (int i=1; i<=(n<<1); i++) G[i].x=(i<=n?B[n-i+1]:0);
poly_mul(F, G, n<<1, n<<1);
int ANS=inf;
int mx=-inf;
for (int i=0; i<n; i++) mx=max(mx, (int)round(F[i+n+1].x));
for (int j=-m; j<=m; j++) {
ANS=min(ANS, ans+j*j*n+2*sum1*j-2*sum2*j-2*mx);
}
printf("%d", ANS);
return 0;
}