Codeforces Round #769 (Div. 2) (A-D题解)

源代码:https://github.com/abmcar/ACM/tree/master/OpenjudgeNow/Codeforces/Codeforces%20Round%20%23769%20(Div.%202)

A. ABC

在这里插入图片描述

题目大意:

在这里插入图片描述

思路:

有这么几种情况

  • 字符串大小为1,此时无法获得长度大于1的回文子串
  • 字符串的大小大于3,此时无论怎么排,都会出现"11",“00”,“101”,"010"这样的回文子串
  • 长度为2,只有"11","00"是回文子串
代码:
void work()
{
    string s;
    int n;
    cin >> n;
    cin >> s;
    if (s.size() == 1)
    {
        cout << "YES" << endl;
        return;
    }
    if (s.size() >= 3)
    {
        cout << "NO" << Endl;
        return;
    }
    if (s == "11" || s == "00")
        cout << "NO" << Endl;
    else
        cout << "YES" << Endl;
}

B. Roof Construction

在这里插入图片描述

题目大意:

在这里插入图片描述

思路:

从位运算的角度看,我们可以发现在最高位相同的情况下,xor的最大值没有最高位不同的两数xor值大,

而且,我们发现必然有两个最高位不同的数排在一起,我们使用0和最高位为1的最小的数拍在一起,此时成本为2^x,成本最低,其他的数按顺序拍到两侧即可

代码:
void work()
{
    cin >> n;
    int cnt = 1;
    while (cnt * 2 < n)
        cnt *= 2;
    for (int i = cnt-1; i >= 0; i--)
        cout << i << " ";
    for (int i = cnt; i < n; i++)
     

C. Strange Test

在这里插入图片描述

题目大意:

在这里插入图片描述

思路:

我们知道操作3能够使a,b接近的更多,对于最后一次操作前的a,b,记作a1,b1

总代价:(a1-a)+(b1-b) + ((a1|b1) - b1) + 1 = a1 + (a1|b1) + (1 - a - b)

已知(1-a-b)的代价固定,我们需要做的就是使a1+(a1|b1)最小

我们可以枚举a1,从位运算的角度从高到低考虑

  • 如果 a1 为0 b 为1 则 b1 设置为 1
  • 如果 a1 为0 b 为0 则 b1 设置为 0
  • 如果 a1 为0 b 为1 则 b1 设置为 1
  • 如果 a1 为0 b 为0 则 b1 设置为 1 并停止,此时b需要通过操作2来到b1,最劣情况,因此停止

之后计算代价即可

代码:
void work()
{
    cin >> a >> b;
    int ans = b - a;
    for (int a1 = a; a1 < b; a1++)
    {
        int b1 = 0;
        for (int i = 23; i >= 0; i--)
        {
            if (b & (1 << i))
                b1 = b1 | (1 << i);
            else
            {
                if (a1 & (1 << i))
                {
                    b1 = b1 | (1 << i);
                    break;
                }
            }
        }
        ans = min(ans, a1 - a - b + (a1 | b1) + 1);
    }
    cout << ans << endl;
}

D. New Year Concert

在这里插入图片描述

题目大意:

在这里插入图片描述

思路:

可以发现gcd(1-n)的值是递减的,

如果我们固定l,可以通过二分的方法找到l,r,使得[l,r]为不满足区间

对于一个不满足区间,我们可以更改其中一个数为质数,是的该区间和包含它的区间满足

因此,我们可以枚举l,得到所有不满足区间,之后使用贪心解决这个区间覆盖问题

我们可以使用线段树来快速得到区间的gcd

代码:
cin >> n;
    nums.resize(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> nums[i];
    build(1, 1, n);
    for (int i = 1; i <= n; i++)
    {
        int nowL = i + 1;
        int nowR = n;
        int ans = i;
        while (nowL <= nowR)
        {
            int nowMid = (nowL + nowR) / 2;
            if (query(1, 1, n, i, nowMid) >= nowMid - i + 1)
            {
                ans = nowMid;
                nowL = nowMid + 1;
            }
            else
                nowR = nowMid - 1;
        }
        // cout << i << " " << ans << endl;
        if (query(1, 1, n, i, ans) == ans - i + 1)
            segs[ans].push_back(i);
    }
    int nowPos = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int it : segs[i])
        {
            // cout << i << " " << it << endl;
            if (it > nowPos)
            {
                ans++;
                nowPos = i;
            }
            // cout << nowPos << " " << ans << endl;
        }
        cout << ans << " ";
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Abmcar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值