吴迪说他化学会考上十分钟就想出来了,太神了%%%不过我也十分钟
但是调了一个多小时啊大草
懒得人话翻译了,自己康吧:
我的室友(真的是室友吗?)最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有 \(n\) 个装饰物,并且每个装饰物都有一定的亮度。
但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的非负整数 \(c\)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 \(1 \sim n\),其中 \(n\) 为每个手环的装饰物个数, 第 \(1\) 个手环的 \(i\) 号位置装饰物亮度为 \(x_i\),第 \(2\) 个手环的 \(i\) 号位置装饰物亮度为 \(y_i\),两个手环之间的差异值为(参见输入输出样例和样例解释):
\[\sum\limits_{i=1}^{n}(x_i-y_i)^2\]
麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?
对于 \(100\%\) 的数据,\(1 \le n \le 50000, 1 \le a_i \le m \le 100。\)
考虑加上一个\(c\)之后式子变为
\[\sum\limits_{i=1}^{n}(x_i-y_i+c)^2\]
拆一下
\[=\sum\limits_{i=1}^{n}x_i^2+y_i^2-2x_iy_i+c^2+c(x_i-y_i)\]
发现求个\(\sum\limits_{i=1}^{n}x_iy_i\)就完了
记\(x^{'}\)为\(x\)翻转后的序列,那么我们只要求\(\sum\limits_{x=1}^{n}x_{n-i+1}^{'}y_i\)
发现是个卷积,但是对齐的位置可能不一样怎么办呢?
可以倍长一下\(x_i\)再翻转,然后在\(ntt\)之后的系数数组的\(x_{n+1}\sim x_{n+n}\)中选一个
就切了
多项式题目的边界真tm恶心
吴迪的代码为什么那么短啊
#include
using namespace std;
namespace red{
#define int long long
#define lowbit(x) ((x)&(-x))
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=5e5+10,p=998244353,g=3,gi=332748118;
int n,m,limit,len;
int suma,sumb,sum;
int ret=1e9+7;
int a[N],pos[N];
int b[N];
inline int fast(int x,int k)
{
int ret=1;
while(k)
{
if(k&1) ret=ret*x%p;
x=x*x%p;
k>>=1;
}
return ret;
}
inline void ntt(int *a,int inv)
{
for(int i=0;i=p) a[j+k]-=p;
a[j+k+mid]=x-y;
if(a[j+k+mid]<0) a[j+k+mid]+=p;
}
}
}
}
inline void main()
{
n=read(),m=read();
for(int i=1;i<=n;++i) a[i]=a[i+n]=read(),suma+=a[i],sum+=a[i]*a[i];
for(int i=1;i<=n;++i) b[i]=read(),sumb+=b[i],sum+=b[i]*b[i];
reverse(a+1,a+2*n+1);
for(limit=1;limit<=3*n;limit<<=1) ++len;
for(int i=0;i>1]>>1)|((i&1)<<(len-1));
ntt(a,1),ntt(b,1);
for(int i=0;i