专栏文章

题解:AT_arc112_b [ARC112B] -- - B

AT_arc112_b题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqdhrfb
此快照首次捕获于
2025/12/04 03:01
3 个月前
此快照最后确认于
2025/12/04 03:01
3 个月前
查看原文

思路

步骤 1

若有一条数轴,可以将他分成正半轴、负半轴和 0{0}
  • 操作 1 不能连续用,因为 1×1=1{-1 \times -1 = 1}
  • 操作 2 总是向左得到数。因为 C2{C - 2}B1{B - 1}

步骤 2

那,如何向右得到数呢?
很简单,只需要遵照这几步:
  1. 只需要先使用一次操作 1;(当且仅当 B{B} 是一个正数,负数跳过这一步)
  2. 再使用任意多次操作 2;
  3. 最后使用一次操作 1。

步骤 3

那么根据 C{C}奇偶性来讨论:
  • Cmod2=1{C \bmod 2 = 1},说明我们应该可以使用奇数次操作 1(假设其是 p{p} 次)并且可以使用 (Cp)÷2{(C - p) \div 2} 次操作 2。
奇数次使用操作 1,不代表不可以向右扩展!我们可以使用偶数 +1{+1} 次,这样的话就可以向右扩展!
  • Cmod2=0{C \bmod 2=0},满足了向右扩展不会剩下任何钱;同时,也可以选择要么全部使用操作 2 或使用偶数次操作 1

步骤 4

此时,可以使用桶来存储可以得到的数。
因为桶就有去重作用!

大体代码

CPP
#include<iostream>
using namespace std;
using ll=long long;
ll buk[1000000],tms,bse,s;
int main()
{
    /*这里我选择使用操作 1 和操作 2 连续使用,能保证要么最后的操作 1 可以用上,要么不操作*/
    scanf("%lld%lld",&bse,&tms);
    bse=bse<0?-bse,tms--:bse;                                   //跟下面的操作有关。
    buk[bse]=1;
    if(bse==0)
    {
        return printf("%d",tms/2+tms/1-1);//0不是负数,所以不能乘上 -1!
    }
    while(tms>=0)
    {
        if(tms>=1)
        {
            buk[bse]++;             //注意,由于 C++ 不能操纵负数组,我就将数组压缩成正负半轴一起用。
            tms--;
        }
        if(tms%2==0)
        {
            buk[--bse]++;
            tms-=2;
        }
    }
    for(int i=0;i<1000000;i++)
    {
        s+=buk[i];                   //完结撒花
    }
    return 0;
}

提示

  1. 使用 long long 来存储。因为 long long 的范围是 263{-2^{63}}2631{2^{63}-1},这个值的极限在1018{-10^{18}} 外或 1018{10^{18}} 外。
  2. 对于 0{0} 的情况,两种(见步骤 3)都可以用!
  3. 岛国水题需要换行!

评论

0 条评论,欢迎与作者交流。

正在加载评论...