AcWing 第82场周赛

AcWing 第82场周赛

竞赛 - AcWing

B 4783. 多米诺骨牌 - AcWing题库

模拟题,考察代码描述问题的能力。

由题意所给的数学形式化定义中看出,所给的骨牌初始序列 LR 的顺序一定是相互交错的,即 ...LRLRLRLR...

所以,一旦遇到 L ,那么下一个一定是 R ;一旦遇到 R ,那么下一个一定是 L

Snipaste_2022-12-18_01-31-35.png

所以我们要处理的是2种区间:

  • L ... R
  • R ... L

对于初始序列的两端,由于可能是 . 开头,所以对初始序列的两端做初始处理,然后得到中间的两端为 LR 的序列。

  • 对于 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 n0 一共产生 n + 1 n+1 n+1 个空位,因为 0 之间必须间隔 1

  • 最少 1 的情况:01序列两端都是 0 ,则有中间要填充 n − 1 n-1 n1 个空位,此时序列为:0101..1010 ,于是有 m ≥ n − 1 m \ge n-1 mn1
  • 最多 1 的情况:01序列的 n + 1 n+1 n+1 个空位全部由 11 填充,此时序列为:11011...11011 ,于是有 m ≤ 2 × ( n + 1 ) m \le 2 \times (n+1) m2×(n+1)

于是可以先对不满足上述两条的数据进行特判,然后对合法输入进行分析:

策略是:

  • m > n − 1 m > n-1 m>n1 时,由于 1 的数量完全够,所以可以先尽可能用掉,防止现在保守导致后面放不完。先摆放 11 ,放了1个 11 自然要放1个 0 隔开,放了1个 0 自然再开始放 1 ,如此进行
  • 等到 m ≤ n − 1 m \le n-1 mn1 时,1 的数量刚刚好了,现在每次只能放 1 了。先摆放 1 ,再摆放 0 ,如此进行

最后如果剩余 0 0 0 个或 1 1 1 个或 2 2 21 ,直接摆放在末尾即可。

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值