题目链接
题目解法
考虑
2
s
−
a
i
2s-a_i
2s−ai 类似翻转操作,于是把数列放在数轴上做
考虑一次操作是把
a
1
,
.
.
.
,
a
n
a_1,...,a_n
a1,...,an 绕
s
s
s 翻转,且没有数为负数
可以得到 2 个性质:
-
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an 中最大最小值一定为
a
1
,
a
n
a_1,a_n
a1,an,且距离不变
所以可以把求最小的最大值 变为 求最小的最小值 - 任何时候数列一定只会有 2 种形态:
a 1 , . . . , a n : A a_1,...,a_n:A a1,...,an:A 形态
a n , . . . , a 1 : B a_n,...,a_1:B an,...,a1:B 形态
考虑有
A
A
A 到
B
B
B,绕
a
i
a_i
ai 翻转
那么
a
n
a_n
an 会变为
2
a
i
−
a
n
2a_i-a_n
2ai−an,是当前序列中的最小值,那么当前操作把最小值变小了
a
1
+
a
n
−
2
a
i
a_1+a_n-2a_i
a1+an−2ai
考虑
B
B
B 操作是
A
A
A 操作的相反操作,那么绕
a
i
a_i
ai 翻转的效益一定可以为
b
i
=
∣
a
1
+
a
n
−
2
a
i
∣
b_i=|a_1+a_n-2a_i|
bi=∣a1+an−2ai∣(可能在奇数次操作,也可能在偶数次操作)
考虑证明
a
i
a_i
ai 一定可以造成
∣
a
1
+
a
n
−
2
a
i
∣
|a_1+a_n-2a_i|
∣a1+an−2ai∣ 的效益
如果当前一步
a
i
a_i
ai 造成的效益为
−
∣
a
1
+
a
n
−
2
a
i
∣
-|a_1+a_n-2a_i|
−∣a1+an−2ai∣,那么可以先翻转
a
n
a_n
an,再翻转
a
i
a_i
ai,然后翻转
a
1
a_1
a1 ,就可以达到序列往前平移
∣
a
1
+
a
n
−
2
a
i
∣
|a_1+a_n-2a_i|
∣a1+an−2ai∣ 的效果
所以当前序列可以往前平移的值为
x
1
b
1
+
x
2
b
2
+
.
.
.
+
x
n
b
n
x_1b_1+x_2b_2+...+x_nb_n
x1b1+x2b2+...+xnbn
根据裴蜀定理,这个值一定为
(
b
1
,
b
2
,
.
.
.
,
b
n
)
(b_1,b_2,...,b_n)
(b1,b2,...,bn) 的倍数
所以答案为
a
n
−
a
1
+
a
1
%
d
(
d
=
(
b
1
,
b
2
,
.
.
.
,
b
n
)
)
a_n-a_1+a_1\% d\;(d=(b_1,b_2,...,b_n))
an−a1+a1%d(d=(b1,b2,...,bn))
#include <bits/stdc++.h>
using namespace std;
const int N(200100);
int n,a[N],b[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=abs(2*a[i]-a[1]-a[n]);
int res=b[1];
for(int i=2;i<=n;i++) res=__gcd(res,b[i]);
printf("%d",a[1]%res+a[n]-a[1]);
return 0;
}