折纸

Description

\(s\) 很 喜欢折纸。

有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为 \(n\) 个单位长度,并且在每份的边界处分别标上数字 \(0\) ~ \(n\)

然后小 \(s\) 开始无聊的折纸,每次他都会选择一个数字,把纸带沿这个数字当前所在的位置翻折(假如已经在边界上了那就相当于什么都不做)。

\(s\) 想知道 \(M\) 次翻折之后纸带还有多长。

Input

输入文件fold.in的第一行包含两个正整数 \(N\)\(M\) ,表示纸带的长度和操作的次数。接下来的一行包含 \(M\) 个整数 \(D_i\) ,其中 \(D_i\) 表示第 \(i\) 次选择的数字。

Output

输出文件为 \(fold.out\) 。输出文件只有一个数字,即纸带最后的长度。

Sample

Sample Input

5 2
3 5

Sample Output

2

Limit

$60% $ 的数据中 \(N \le 3000,M\le 3000\)

\(100\%\) 的数据中 \(N\le 10^{18},M\le3000\)

Solution

每次翻折的时候就计算一下翻折点现在的坐标值。

#include<bits/stdc++.h>
using namespace std;
#define M 3001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define ll long long
inline ll read() {
	ll x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
ll n, l, r, a[M];
int m;
int main() {
	freopen("fold.in", "r", stdin); freopen("fold.out", "w", stdout);
	r = n = read(); m = read();
	rep(i, 1, m) {
		ll x = a[i] = read(); rep(j, 1, i - 1) if(a[j] < x) x = (a[j] << 1) - x; a[i] = x;
        l = min(l, (x << 1) - r); r = x; if(l > r) swap(l, r);
	}
	printf("%I64d", r - l);
	return 0;
}
posted @ 2018-02-24 15:23  aziint  阅读(259)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.