CF 1452题解

A. Robot Program

如果没有限制条件的话,答案就是 n + m n + m n+m
考虑限制条件,那么我们每走一步就要换一种走法, 很明显交替走是最优的,如果不能交替走,就停在原地。
很明显答案就是 n + m + m a x ( m a x ( n , m ) − m i n ( n , m ) − 1 , 0 ) n + m + max(max(n, m) - min(n, m) - 1, 0) n+m+max(max(n,m)min(n,m)1,0)

AC代码:

#include <bits/stdc++.h>

using namespace std;

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        int n, m;
        cin >> n >> m;
        cout << n + m + max(max(n, m) - 1 - min(n, m), 0) << '\n';
    }
}

B. Toy Blocks

观察可得重要性质:放置完后,总积木数一定能被 m o d ( n − 1 ) mod (n - 1) mod(n1)
这个性质无法推过第三个样例,所以取最大值覆盖下所有的积木盒子,然后两者取更大值。

AC代码:

#include <bits/stdc++.h>

using namespace std;

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        long long sum = 0, ans = 0;
        int max_val = 0;
        vector <int> a(n);
        for(int i = 0; i < n; ++i)
        {
            cin >> a[i];
            sum += a[i];
            max_val = max(max_val, a[i]);
            if(sum % (n - 1) != 0)
                ans = (sum / (n - 1) + 1) * (n - 1);
            else
                ans = sum;
        }
        ans = max(ans, 1ll * max_val * (n - 1));
        ans -= sum;
        cout << ans << '\n';

    }
}

C. Two Brackets

贪心匹配最近的括号

AC代码:

#include <bits/stdc++.h>

using namespace std;

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        string s;
        cin >> s;
        int ans = 0;
        bool ok = 0;
        int len = (int) s.size();
        for(int l = 0, r = 0; l < len; ++l)
        {
            if(s[l] == '(')
            {
                r = max(r, l);
                while(++ r < len)
                {
                    if(s[r] == ')')
                    {
                        ans ++;
                        break;
                    }
                }
            }
        }
        for(int l = 0, r = 0; l < len; ++l)
        {
            if(s[l] == '[')
            {
                r = max(r, l);
                while(++ r < len)
                {
                    if(s[r] == ']')
                    {
                        ans ++;
                        break;
                    }
                }
            }
        }
        cout << ans << '\n';
    }
}

D. Radio Towers

考虑到最初情况 n = 1 n = 1 n=1时, 合法方案数是 1 1 1
我们手推几组样例,发现 合法方案数是为一个斐波那契数列。
根据概率的定义:

P ( A ) = m n P(A)= \frac{m}{n} P(A)=nm

可得答案即为:
a n s = f n − 2 + f n − 1 2 n ans = \frac{f_{n - 2} + f_{n - 1}}{2 ^ n} ans=2nfn2+fn1

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int P = 998244353;

long long ksm(long long a, int b)
{
    long long res = 1;
    while(b)
    {
        if(b & 1)
            res = res * a % P;
        a = a * a % P;
        b >>= 1;
    }
    return res;
}

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    vector <long long> v(n + 5);
    v[1] = v[2] = 1;
    for(int i = 3; i <= n; ++i)
    {
        v[i] = (v[i - 1] + v[i - 2]) % P;
    }
    cout << v[n] * ksm(ksm(2, n), P - 2) % P << '\n';
}

E. Two Editorials

考虑暴力枚举区间长度 k k k,做一个前缀和后缀。
前缀代表:老师A讲课到 i i i 学生最大的贡献。
后缀代表:老师B讲课到 j j j 学生最大的贡献。
考虑贪心策略,以每个学生区间值的中点排序,然后进行枚举即可。
时间复杂度大概是 Θ ( n 2 ) \Theta(n^2) Θ(n2)

AC代码:

#include <bits/stdc++.h>

using namespace std;

struct stu
{
    int l, r;
}s[(int) 2e3 + 5];

bool cmp(stu a, stu b)
{
    return a.l + a.r < b.l + b.r;
}

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int n, m, k;
    cin >> n >> m >> k;
    for(int i = 1; i <= m; ++i)
    {
        cin >> s[i].l >> s[i].r;
    }
    sort(s + 1, s + 1 + m, cmp);
    vector <int> pre(m + 5, 0), suf(m + 5, 0);
    for(int l = 1; l <= n - k + 1; ++l)
    {
        int L = l;
        int R = l + k - 1;
        int res1 = 0;
        for(int i = 1; i <= m; ++i)
        {
            if(R < s[i].l || L > s[i].r)
            {
                pre[i] = max(pre[i], res1);
                continue;
            }
            L = max(L, s[i].l);
            R = min(R, s[i].r);
            res1 += R - L + 1;
            pre[i] = max(pre[i], res1);
            L = l;
            R = l + k - 1;
        }
        int res2 = 0;
        for(int i = m; i >= 1; --i)
        {
            if(R < s[i].l || L > s[i].r)
            {
                suf[i] = max(suf[i], res2);
                continue;
            }
            L = max(L, s[i].l);
            R = min(R, s[i].r);
            res2 += R - L + 1;
            suf[i] = max(suf[i], res2);
            L = l;
            R = l + k - 1;
        }
    }
    int max_val = 0;
    for(int i = 1; i <= m; ++i)
    {
        max_val = max(max_val, pre[i] + suf[i + 1]);
    }
    cout << max_val << '\n';
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值