AtCoder Regular Contest 112 B 思维 数轴区间去重

这篇博客探讨了如何在AtCoder Regular Contest 112B问题中,运用数学策略来处理涉及减法和乘法操作的货币系统。作者分析了不同数额货币下最优操作的边界值,并通过奇偶性判断来确定可能的数值范围。文章还提供了C++代码实现,展示了如何计算给定金额下可能得到的所有数值的个数。

AtCoder Regular Contest 112 B

题目链接

官方题解

Solution

考虑刚刚好使用 C C C

当钱数为 C C C 时,考虑这样一个特殊序列,对数 B B B 做任意次减一操作之后,在乘上 − 1 -1 1 的结果

  • 如果我们乘上奇数次 − 1 -1 1 ,最终每一次减法都会在 B B B 上造成加 1 1 1 的贡献
  • 如果我们乘上偶数次 − 1 -1 1 ,最终每一次减法都会在 B B B 上造成减 1 1 1 的贡献

当钱数 C C C 为奇数时,可以将 C C C 表示为 C = 2 n + 1 C=2n+1 C=2n+1 的形式,考虑尽量少的乘法操作得到的边界值更优,所以我们可以得到 B B B 的范围

  • 一开始进行 n n n 次减法操作得到 B − n B-n Bn,再进行乘法操作得到 − B + n -B+n B+n
  • 一开始进行乘法操作得到 − B -B B ,再进行 n n n 次减法操作得到 − B − n -B-n Bn

当钱数 C C C 为偶数时,可以将 C C C 表示为 C = 2 n C=2n C=2n 的形式,考虑尽量少的乘法操作得到的边界值更优,所以我们可以得到 B B B 的范围

  • C = 0 C=0 C=0 时,只能得到 B B B
  • C > 0 C>0 C>0
    • 如果只进行减法操作,得到 B − n B-n Bn
    • 如果使用一次乘法操作,根据 C C C 为奇数时的做法,得到答案在 B − n + 1 B-n+1 Bn+1 B + n − 1 B+n-1 B+n1

对于原问题,所有能用 C = k C=k C=k 元得到的数,可以用 C = k + 2 C=k+2 C=k+2 元得到。那么,我们就只要考虑 C = k C=k C=k C = k − 1 C=k-1 C=k1 两种情况,其他在他们之间的数都能得到。

C C C 元得到的数为, a , b a,b a,b C − 1 C-1 C1 元得到的数为 c , d c,d c,d,那么得到的所有数就是 [ a , b ] [a,b] [a,b] [ c , d ] [c,d] [c,d] 的元素个数和减去重复元素的个数 0 0 0 或者 m i n ( b , d ) − m a x ( a , c ) min(b,d)-max(a,c) min(b,d)max(a,c) (画图可知)

Code

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

pair<ll, ll> exact(ll B, ll C) {
    ll n = C / 2;
    if (C % 2 != 0) return {-B - n, -B + n};
    else {
        if (C == 0) return {B, B};
        else {
            return {B - n, B + n - 1};
        }
    }
}

int main() {

//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);

//	ios::sync_with_stdio(false);
    ll B, C;
    cin >> B >> C;
    ll ans;
 
//    pair<ll, ll> ab;
//    pair<ll, ll> cd;
//    ab = exact(B, C);
//    cd = exact(B, C - 1);
//    ll a, b, c, d;
//    a = ab.first, b = ab.second, c = cd.first, d = cd.second;

    // C++ 17
    const auto [a, b] = exact(B, C);
    const auto [c, d] = exact(B, C - 1);

    ans = (b - a + 1) + (d - c + 1) - max((ll) 0, min(b, d) - max(a, c) + 1);

    cout << ans << '\n';

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值