AtCoder-agc017 B - Moderate Differences 题解
https://atcoder.jp/contests/agc017/tasks/agc017_b?lang=en
题意:
N个格子排成一行,第一个元素A和最后一个元素B的值已经给出,中间的格子是空的。你需要在每个空格子中填上一个数字,使得任意两个相邻的数满足 a b s ( a [ i + 1 ] − a [ i ] ) ∈ [ C , D ] abs(a[i+1]-a[i])\in[C,D] abs(a[i+1]−a[i])∈[C,D],如果存在这样一个序列输出YES,否则输出NO。
推导:
对于任意的i,有 C ≤ a [ i + 1 ] − a [ i ] ≤ D o r − D ≤ a [ i + 1 ] − a [ i ] ≤ − C C\le a[i+1]-a[i]\le D \quad or\quad-D\le a[i+1]-a[i]\le -C\quad C≤a[i+1]−a[i]≤Dor−D≤a[i+1]−a[i]≤−C,将其分别命名为集合X和Y。
对于整个序列而言,共有N-1个 a [ i + 1 ] − a [ i ] a[i+1]-a[i] a[i+1]−a[i]对元素差,而根据题目条件可推得 ∑ i = 1 n − 1 a [ i + 1 ] − a [ i ] = B − A \sum_{i=1}^{n-1}a[i+1]-a[i]=B-A ∑i=1n−1a[i+1]−a[i]=B−A。
我们不妨设X集合有k对元素差,那相应的集合Y就有N-1-k对元素差。所以可求得下列不等式:
X = k ∗ C ≤ k ∗ ( a [ i + 1 ] − a [ i ] ) ≤ k ∗ D X=k*C\le k*(a[i+1]-a[i])\le k*D\qquad X=k∗C≤k∗(a[i+1]−a[i])≤k∗D Y = ( N − k − 1 ) ∗ − D ≤ ( N − k − 1 ) ∗ ( a [ i + 1 ] − a [ i ] ) ≤ ( N − k − 1 ) ∗ D Y=(N-k-1)*-D\le (N-k-1)*(a[i+1]-a[i])\le (N-k-1)*D Y=(N−k−1)∗−D≤(N−k−1)∗(a[i+1]−a[i])≤(N−k−1)∗D
将X和Y相加: X + Y = k ∗ C − ( N − k − 1 ) ∗ D ≤ ( N − 1 ) ∗ ( a [ i + 1 ] − a [ i ] ) ≤ k ∗ D − ( N − k − 1 ) ∗ C X+Y=k*C-(N-k-1)*D\le(N-1)*(a[i+1]-a[i])\le k*D-(N-k-1)*C X+Y=k∗C−(N−k−1)∗D≤(N−1)∗(a[i+1]−a[i])≤k∗D−(N−k−1)∗C
该式等价于: X + Y = k ∗ C − ( N − k − 1 ) ∗ D ≤ B − A ≤ k ∗ D − ( N − k − 1 ) ∗ C X+Y=k*C-(N-k-1)*D\le B-A\le k*D-(N-k-1)*C X+Y=k∗C−(N−k−1)∗D≤B−A≤k∗D−(N−k−1)∗C
可以这样理解上式:若该序列存在某个数A,那么该数一定是经过若干次 + 不 同 的 ∈ [ C , D ] 的 数 +不同的\in[C,D]的数 +不同的∈[C,D]的数和若干次 − 不 同 的 ∈ [ C , D ] 的 数 -不同的\in[C,D]的数 −不同的∈[C,D]的数得到的,且这两种操作的次数加起来肯定为N-1。例如:对于N=5的情况,可能经历4次加,0次减;3次加,1次减;2次加,2次减… 而每个操作所处的位置是无所谓的(例如样例1的序列为 [ 1 , − 1 , 3 , 7 , 5 ] [1,-1,3,7,5] [1,−1,3,7,5],是通过-C,+C,+D,+C得到的,但如果交换操作的次序为+C,-C,+C,+D得到的序列 [ 1 , 3 , − 1 , 1 , 5 ] [1,3,-1,1,5] [1,3,−1,1,5]同样也是合法的。)
所以对于上式 k ∈ [ 0 , N − 1 ] k\in[0,N-1] k∈[0,N−1],相当于遍历所有加减操作的组合的情况。
所以只要存在经历了某种组合的加减操作后得到的值的范围是包含 B − A B-A B−A的,那么就说明存在这样一个序列。
实现:
#include<iostream>
using namespace std;
typedef long long ll;
ll n, a, b, c, d;
int main() {
scanf("%lld", &n);
scanf("%lld %lld %lld %lld", &a, &b, &c, &d);
for (ll i = 0; i < n; i++) {
if ((b - a) >= (i * c - (n - i - 1) * d)
&& (b - a) <= (i * d - (n - i - 1) * c)) {
printf("YES");
return 0;
}
}
printf("NO");
return 0;
}