# AtCoder-agc017 B - Moderate Differences 题解

12 篇文章 0 订阅

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 Ca[i+1]a[i]DorDa[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=1n1a[i+1]a[i]=BA

我们不妨设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=kCk(a[i+1]a[i])kD 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=(Nk1)D(Nk1)(a[i+1]a[i])(Nk1)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=kC(Nk1)D(N1)(a[i+1]a[i])kD(Nk1)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=kC(Nk1)DBAkD(Nk1)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,N1],相当于遍历所有加减操作的组合的情况。

所以只要存在经历了某种组合的加减操作后得到的值的范围是包含 B − A B-A BA的,那么就说明存在这样一个序列。

实现:
#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值