分析

我们发现,对于一个序列进行旋转操作,其实可以等同于只对一个序列进行操作。然后加上改变量所以题意其实就是要我们求 。 我们先把中间的式中拆开 。变成了这个式子。那么我们可以考虑枚举 。那么现在就只有 是没法很快求出来的了。可以令一个数组 ,保证 ,那么现在,就是要求 ,这个就是个标准的卷积形式了。我们把 破环成链。现在就只需要让 做一次多项式乘法就好了。那我们取那一部分的答案呢? 考虑到我们是把 倍长了的。所以我们实际需要的答案应该在 这些项中去寻找。其实可以不用枚举 ,因为我们已经转换为一个二次函数了,那么我只需要考虑二次函数的对称轴。但是这个不是实数,所以要考虑 。两个可能的最优解。如果要枚举 ,那么我们的枚举范围也应该是 ,因为出了这个范围,答案一定会越变越大。最后时间复杂度为

小结

这类非卷积形式,可以考虑通过翻转序列,来达到构造卷积的形式。

代码

#include<bits/stdc++.h>
using namespace std;
const int p = 998244353,Gi = 3,N = 1e6 + 10;
int read() {
    int x = 0,f = 0;char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();}
    while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
    return f ? -x : x;
}
int A[N],B[N],C[N],L,limit = 1,R[N],n,m,res,resA,resB,ans = 0x3f3f3f3f;
int qpow(int x,int b) {
    int a = 1;for(;b;b>>=1,x = 1LL*x*x%p) {
        if(b&1) a = 1LL * a * x % p;
    }
    return a;
}
void ntt(int *a,int type) {
    for(int i = 0;i < limit;i++) if(i < R[i]) swap(a[i],a[R[i]]);
    for(int mid = 1;mid < limit;mid <<= 1) {
        int wn = qpow(Gi,(p-1)/(mid<<1));
        for(int i = 0;i < limit;i += (mid<<1)) {
            int w = 1;
            for(int j = 0;j < mid;j++,w = 1LL * w * wn % p) {
                int x = a[i + j],y = 1LL * w * a[i + j + mid] % p;
                a[i + j] = (x + y) % p;a[i + j + mid] = (x - y + p) % p;
            }
        }
    }
    if(type == -1) {
        int inv = qpow(limit,p - 2);
        reverse(a+1,a+limit);
        for(int i = 0;i < limit;i++) a[i] = 1LL * a[i] * inv % p;
    }
}
int main()
{
    n = read();m = read();
    for(int i = 1;i <= n;i++) A[i] = read();
    for(int i = 1;i <= n;i++) B[i] = read();
    for(int i = 1;i <= n;i++) {
        res += A[i] * A[i] + B[i] * B[i];
        resA += A[i];resB += B[i];
    }
    for(int i = 1;i <= n;i++) {
        C[i + n] = C[i] = A[i];
    }
    reverse(B+1,B+n+1);
    while(limit <= n+n+n) limit <<= 1,L++;
    for(int i = 0;i < limit;i++) R[i] = (R[i >> 1] >> 1)|((i & 1) << L - 1);
    ntt(C,1);ntt(B,1);
    for(int i = 0;i < limit;i++) C[i] = (1LL * C[i] * B[i]) % p;
    ntt(C,-1);
//    for(int i = 0;i < limit;i++) cout << C[i] << " ";cout << endl;
    for(int i = 1;i <= n;i++) {
        for(int j = -m;j <= m;j++) {
            ans = min(ans,res+j*j*n+2*j*(resA - resB)-2*(C[i+n]));
        }
    }
    cout << ans << endl;
    return 0;
}