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\) ,求出最短序列的长度,这个序列需要满足:
- \(a\) 为序列的 \(Mex\) 函数值。
- 序列所有数字的 \(Xor\) 值为 \(b\) 。
分析
首先,需要满足 \(Mex\) 为 \(a\) ,那么序列一定存在的数值为 (1, 2, ... , a - 1)
下接来要满足 \(Xor\) 性质。
假设当前序列 \(xor\) 值为 \(k\) 。
对于给出的值 \(b\) ,我们一定可以找出一个值 \(r\) ,使 $k \ xor \ r = b $。(分类讨论某一个二进制中 \(k\) 和 \(b\) 相同与不相同的情况,可以构造 \(r\))。
分类讨论。
- \(k\) 已经等于 \(b\) ,我们可以不用构造 \(r\) ,这样最小数量就为 \(a\)。
- \(r\) 不等于 \(a\) ,同时满足两个性质,需要 \(a + 1\) 个数字,且都是必须要的,所以 \(a + 1\) 为最小数量。
- \(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
// 先鸽了