Codeforces Round #742 (Div. 2) [A - D]

Codeforces Round #742 (Div. 2) [A - D]

A. Domino Disaster

题意

有一个 \(2 \times n\)​ 的矩阵,Alice要在这个矩阵上放置 \(1 \times 2\) 的小方块,'U'表示所属小方块竖放且当前位置为上部,'D'表示下部,'L'表示小方块横放且当前位置为左边,'R'表示右边。给出某一行摆放状态,求出另一行的摆放状态(任意一个合法状态,题目保证有合法解)。

分析

分析给出的状态 \(S\)​ ,如果当前位置为‘L'或R',那么另一行一定可以摆放相同的状态,如果为'U'或者'D',那么对应的位置一定摆放同一个方块的另一侧。

所以只需要把给定状态的 \(S\) 中 'U' 和 'D' 改变状态即可(题目保证一定有合法解)。

Code

void solve ()
{
    int n; cin >> n;
    string s; cin >> s;
    for (int i = 0; i < s.size(); i ++ )
    {
        if (s[i] == 'U') s[i] = 'D';
        else if (s[i] == 'D') s[i] = 'U';
    }
    cout << s << endl;
}

B. MEX or Mix up

题意

Alice给出两个数字 \(a 、 b\)​ ,求出最短序列的长度,这个序列需要满足:

  1. \(a\) 为序列的 \(Mex\) 函数值。
  2. 序列所有数字的 \(Xor\) 值为 \(b\)

分析

首先,需要满足 \(Mex\)​ 为 \(a\)​ ,那么序列一定存在的数值为 (1, 2, ... , a - 1)

下接来要满足 \(Xor\)​ 性质。

假设当前序列 \(xor\) 值为 \(k\)

对于给出的值 \(b\)​ ,我们一定可以找出一个值 \(r\)​ ,使 $k \ xor \ r = b $​。(分类讨论某一个二进制中 \(k\)\(b\) 相同与不相同的情况,可以构造 \(r\))。

分类讨论。

  1. \(k\) 已经等于 \(b\) ,我们可以不用构造 \(r\) ,这样最小数量就为 \(a\)
  2. \(r\) 不等于 \(a\) ,同时满足两个性质,需要 \(a + 1\) 个数字,且都是必须要的,所以 \(a + 1\) 为最小数量。
  3. \(r\) 等于 \(a\) ,取 \(r \ = \ a\)不满足 \(Mex\) ,此时我们可以取 \(r \ > \ a\) ,新序列 \(xor\) 值为 \(k_{new}\) ,再构造一个 \(r_{new}\) 使得满足 \(xor\) 值为 \(b\)。满足,最小数量为 \(a + 2\)

code

int Xor[N]; // [1 .. n]序列 xor值前缀和

void init ()
{
    for (int i = 1; i < N; i ++ )
        Xor[i] = Xor[i - 1] ^ i;
}

void solve ()
{
    int a, b; cin >> a >> b;
    if (Xor[a-1] == b) cout << a << endl; // 如果xor值正好等于b,那么不需要增加数字
    else if ((Xor[a-1] ^ a) == b) cout << a + 2 << endl; // 如果a和序列xor值为b,不能取a,那么我们需要另取两个值
    else cout << a + 1 << endl; // 加的数字不是a,只需要加这一个数字即可
}

C. Carrying Conundrum

题意

Alice把加法进位算错了,对于一个两数相加的加法,她把所有的进位向左挪了一个列。

给出一个数字 \(n\)​​ ,问在Alice错误的加法法则下,有多少个加法式子相加为 \(n\)​ 。( 式子中加法都为正数, \(1 + 2\)​ 和 \(2 + 1\)​算作不同,\(1 + 1\)​ 和 \(1 + 1\)​​ 相同)

分析

卡了很久的题目,但是想清楚了其实很简单。

首先进位列向左移动一列代表什么?

在正常的加法中,偶数位向奇数位进位,奇数位向偶数位进位。但是向左移动,那么奇数位向奇数位进位,偶数位向偶数位进位

那么我们只需要按照奇偶位拆分 \(n\)\(a、b\) ,那么对于 \(a\)\(b\) 而言其实都是正常的加法法则,只需要简单相乘即可。

注意加数不能为 \(0\) ,所以要减去两个加数为 \(0\) 的情况。

公式为 \((a + 1) \times (b + 1) - 2\)

void solve ()
{
    string s; cin >> s;
    int a = 0, b = 0;
    for (int i = 0; i < s.size(); i ++ )
    {
        if (i % 2) a = a * 10 + s[i] - '0';
        else b = b * 10 + s[i] - '0';
    }
    cout << (a + 1) * (b + 1) - 2 << endl;
}

D. Expression Evaluation Error

题意

给出一个数 \(s\)​ ,求问,将它拆分成 \(n\) 个数字(相加为 \(s\)),在 \(11\) 进制下相加并化作 \(10\)​ 进制的数字,怎样拆分可以使得这个数字最大?

分析

比较数字大小,我们直接用 \(11\) 进制下比较即可,无需化成 \(10\) 进制。

我们发现,无论怎么拆分,由于相加都为 \(s\) ,那么在 \(11\) 进制下,这些数字相加一定不会超过 \(s\) (看作十进制表示)。

我们只需要让拆分出来的数字,在不进位的情况下相加为 \(s\) 即可,这样 \(10\) 进制和 \(11\) 进制表示是一样的,达到了最大值。

贪心拆,找10的倍数,比如 \(197 = 100 + 10 + 87\) ,这样一定没有进位。

Code

// 先鸽了
posted @ 2021-09-06 23:39  Horb7  阅读(67)  评论(0编辑  收藏  举报