AcWing 第82场周赛
B 4783. 多米诺骨牌 - AcWing题库
模拟题,考察代码描述问题的能力。
由题意所给的数学形式化定义中看出,所给的骨牌初始序列 L
和 R
的顺序一定是相互交错的,即 ...LRLRLRLR...
所以,一旦遇到 L
,那么下一个一定是 R
;一旦遇到 R
,那么下一个一定是 L
。
所以我们要处理的是2种区间:
L ... R
R ... L
对于初始序列的两端,由于可能是 .
开头,所以对初始序列的两端做初始处理,然后得到中间的两端为 L
或 R
的序列。
- 对于
L ... R => <- ... ->
:显然中间区间的所有牌都不会倒 - 对于
R ... L => -> ... <-
:显然只有最中间的牌不会倒- 如果区间牌数为奇数,则只剩下1张牌不会倒
- 如果区间牌数位偶数,则所有牌都会倒
#include <bits/stdc++.h>
using namespace std;
int n, ans;
string str;
int main() {
cin >> n >> str;
int l = 0;
while (l < n && str[l] == '.')
l++;
if (l == n) {
cout << n;
return 0;
}
if (str[l] == 'R')
ans += l - 0;
int r = n - 1;
while (0 <= r && str[r] == '.')
r--;
if (r == -1) {
cout << n;
return 0;
}
if (str[r] == 'L')
ans += n - 1 - r;
int cnt = 0;
for (int i = l + 1; i <= r; i++) {
// 在遇到L或R之前,统计"."的个数
if (str[i] == '.') cnt++;
else {
// R ... L => -> ... <-
if (str[i] == 'L') {
ans += cnt & 1 ? 1 : 0;
cnt = 0;
}
// L ... R => <- ... ->
else {
ans += cnt;
cnt = 0;
}
}
}
cout << ans;
return 0;
}
C AcWing 4784. 构造序列 - AcWing
模拟题,考察构造能力。
数学思路就是高中数学排列组合的「隔板法」。
n
n
n 个 0
一共产生
n
+
1
n+1
n+1 个空位,因为 0
之间必须间隔 1
,
- 最少
1
的情况:01序列两端都是0
,则有中间要填充 n − 1 n-1 n−1 个空位,此时序列为:0101..1010
,于是有 m ≥ n − 1 m \ge n-1 m≥n−1 - 最多
1
的情况:01序列的 n + 1 n+1 n+1 个空位全部由11
填充,此时序列为:11011...11011
,于是有 m ≤ 2 × ( n + 1 ) m \le 2 \times (n+1) m≤2×(n+1)
于是可以先对不满足上述两条的数据进行特判,然后对合法输入进行分析:
策略是:
- 在
m
>
n
−
1
m > n-1
m>n−1 时,由于
1
的数量完全够,所以可以先尽可能用掉,防止现在保守导致后面放不完。先摆放11
,放了1个11
自然要放1个0
隔开,放了1个0
自然再开始放1
,如此进行 - 等到
m
≤
n
−
1
m \le n-1
m≤n−1 时,
1
的数量刚刚好了,现在每次只能放1
了。先摆放1
,再摆放0
,如此进行
最后如果剩余
0
0
0 个或
1
1
1 个或
2
2
2 个 1
,直接摆放在末尾即可。
#include <bits/stdc++.h>
using namespace std;
int n, m;
int main() {
scanf("%d%d", &n, &m);
if (m < n - 1 || m > ((n + 1) << 1)) {
printf("-1");
return 0;
}
while (n) {
// 先摆放11或1,取决于m够不够
// 1. m>n-1时,for循环摆放11,printf摆放0
// 2. m<=n-1时,由于m和n只相差1,所以m--和n--会使得重新满足m>n-1,于是for循环摆放1,printf摆放0
for (int i = 1; i <= 2; i++)
if (m > n - 1) {
printf("1");
m--;
} else
break;
// 再摆放0隔开
printf("0");
n--;
}
// 最后把剩余的1摆放完(此时m=0或1或2)
while (m--)
printf("1");
return 0;
}