-1+2-1
这一看以为是贪心推了半天最后发现是数学题(悲)
题目
给你一个长度为n的序列A,A = ( A 1 , A 2 , A 3 . . . A n A_1,A_2,A_3...A_n A1,A2,A3...An)
你可以反复的进行如下操作:选择一个 i i i,然后让 A i A_i Ai加上 2 2 2 , A i − 1 A_{i-1} Ai−1 减去 1 1 1 , A i + 1 A_{i+1} Ai+1 减去 1 1 1 。注意该序列是循环的,也就是操作 A 0 A_0 A0 等同于操作 A n A_n An,操作 A n + 1 A_{n+1} An+1 等同与操作 A 1 A_1 A1。
如果通过这样的操作可以将A序列全部变为0的话,请你输出最小步数,如果不可以的话,输出-1。
Input
第一行一个正整数 n n n 3 ≤ n ≤ 200000 3 \le n \le 200000 3≤n≤200000。
第二行n个正整数,第i个数代表 A i A_i Ai − 100 ≤ A i ≤ 100 -100 \le A_i \le 100 −100≤Ai≤100。
Output
输出一行一个正整数,最小步数或者-1。
Samples
4
3 0 -1 -2
5
对于样例,可以操作 2 3 3 4 4可以使数组变为全0
思路
- 显而易见, − 1 + 2 − 1 = 0 -1+2-1=0 −1+2−1=0 ,意味着每一次操作不会改变原数组的总和,则:
特判 1 : ∑ A i = 0 \sum{A_i}=0 ∑Ai=0
- 设 f i f_i fi 为对第 i i i 个数字的修改次数,求 ∑ f i \sum{f_i} ∑fi ,则有:
2 ∗ f i − f i − 1 − f i + 1 = − A i 2*f_i-f_{i-1}-f_{i+1}=-A_i 2∗fi−fi−1−fi+1=−Ai
- 通过移项可得:
( f i + 1 − f i ) − ( f i − f i − 1 ) = A i (f_{i+1}-f_i)-(f_i-f_{i-1})=A_i (fi+1−fi)−(fi−fi−1)=Ai
- 设 B i = f i + 1 − f i B_i=f_{i+1}-f_i Bi=fi+1−fi , 3 3 3 式转化为:
B i − B i − 1 = A i B_i-B_{i-1}=A_i Bi−Bi−1=Ai
- 由 4 4 4 式 对 A i A_i Ai 累加推的:
B i = ∑ j = 1 i A j + B 1 − A 1 B_i=\sum_{j=1}^{i}A_j+B_1-A_1 Bi=∑j=1iAj+B1−A1
- 由 5 5 5 式 对 B i B_i Bi 累加推的:
∑ i = 1 n B i = n ∗ ( B 1 − A 1 ) + i ∗ ∑ j = 1 i A i \sum_{i=1}^nB_i=n*(B_1-A_1)+i * \sum_{j=1}^iA_i ∑i=1nBi=n∗(B1−A1)+i∗∑j=1iAi
- 化简 6 6 6 式:
∑ i = 1 n B i = n ∗ B 1 − ∑ j = 2 n ( n + 1 − j ) ∗ A j \sum_{i=1}^nB_i=n*B_1-\sum_{j=2}^n(n+1-j)*A_j ∑i=1nBi=n∗B1−∑j=2n(n+1−j)∗Aj
- 累加可得:
∑ i = 1 n B i = f n + 1 − f 1 = 0 \sum_{i=1}^nB_i=f_{n+1}-f_1=0 ∑i=1nBi=fn+1−f1=0
- 由 7 7 7 式 移项得:
B i = ∑ i = 2 n ( n + 1 − i ) ∗ A i n = ∑ j = 1 i A j + B 1 − A 1 B_i=\frac{\sum_{i=2}^n(n+1-i)*A_i}{n}=\sum_{j=1}^{i}A_j+B_1-A_1 Bi=n∑i=2n(n+1−i)∗Ai=∑j=1iAj+B1−A1
通过数组 f f f 的定义,由于 f i f_i fi 是第 i i i 个数的操作次数,又因为我们需要总操作次数最小。
因此我们要找到一个数 x x x ,令 f x = 0 f_x=0 fx=0 ,实际上对于每个 i i i ,答案最小为 f i − f x f_i-f_x fi−fx 。
总答案为 ∑ i = 1 n f i − n ∗ f x \sum_{i=1}^nf_i-n*f_x ∑i=1nfi−n∗fx
令 C i = f i − f x C_i=f_i-f_x Ci=fi−fx 。
为了方便计算,我们令 x x x 的初值为1,因此
对于 i = 0 , C 1 = 0 i=0,C_1=0 i=0,C1=0,对于 i > = 2 , C i = C i − 1 + B i − 1 i>=2,C_i=C_{i-1}+B_{i-1} i>=2,Ci=Ci−1+Bi−1
因此要找到一个 x x x 满足 ∑ i = 1 n f i − n ∗ f x \sum_{i=1}^nf_i-n*f_x ∑i=1nfi−n∗fx 最小
即 找到最小的 C i C_i Ci 为minn,对于每个 C i − = m i n n C_i-=minn Ci−=minn
再将 c i c_i ci 求和就为答案 ∑ i = 1 n f i − n ∗ f x \sum_{i=1}^nf_i-n*f_x ∑i=1nfi−n∗fx
#include <iostream>
using namespace std;
#define int long long
int sum, n, a[2000005], m, x, s;
signed main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
a[i] += a[i - 1]; //算前缀和
sum += a[i];
}
if (a[n] != 0) //显然,-1+2-1=0,操作前后的总和不变,则总和不为0则不能操作
{
cout << "-1" << endl;
return 0;
}
for (int i = 1; i <= n; i++) //不难发现,操作与顺序无关,只与各位置操作次数有关
{
if (sum % n)
{
cout << "-1";
return 0;
}
s += sum / n - a[i];
m = max(m, s);
x += s;
}
cout << n * m - x << endl;
return 0;
}