• Codeforces Round #804 (Div. 2) 题解


    A. The Third Three Number Problem

    题意

    给你一个整数 \(n\) ,构造满足等式 \((a \bigoplus b)+(b \bigoplus c)+(a \bigoplus c)=n\) 的三个整数 \(a,b,c\) ,或说明这样的整数并不存在。

    题目分析

    根据样例猜了下如果是奇数则不存在,是偶数的话随便构造下就好。

    AC代码

    #include <bits/stdc++.h>
    #include <limits>
    #define IOS                           \
        std::ios::sync_with_stdio(false); \
        std::cin.tie(0);                  \
        std::cout.tie(0);
    using PII = std::pair<int, int>;
    using ll = long long;
    
    void solve()
    {
        ll n;
        std::cin >> n;
        if (n % 2 == 1)
            std::cout << -1 << '\n';
        else
            std::cout << n / 2 << ' ' << 0 << ' ' << 0 << '\n';
    }
    
    int main()
    {
        IOS;
        int t;
        std::cin >> t;
        while (t--)
            solve();
        return 0;
    }
    

    B. Almost Ternary Matrix

    题意

    给一个 \(n\)\(m\) 列的矩阵黑白染色,使得其中每个单元格 \((i,j)\) 的邻格中恰有两个不同色。

    题目分析

    跟着样例画了画发现按 \({\begin{bmatrix}1&0\\0&1\end{bmatrix}}\)\({\begin{bmatrix}0&1\\1&0\end{bmatrix}}\) 交替染色即可。

    AC代码

    #include <bits/stdc++.h>
    #include <limits>
    #define IOS                           \
        std::ios::sync_with_stdio(false); \
        std::cin.tie(0);                  \
        std::cout.tie(0);
    using PII = std::pair<int, int>;
    using ll = long long;
    
    int map[55][55];
    
    void solve()
    {
        int n, m;
        std::cin >> n >> m;
        for (int i = 1, f1 = 1; i <= n; i += 2, f1 ^= 1)
        {
            if (f1 & 1)
            {
                for (int j = 1, f2 = 1; j <= m; j += 2, f2 ^= 1)
                {
                    if (f2 & 1)
                        map[i][j] = map[i + 1][j + 1] = 1;
                    else
                        map[i][j + 1] = map[i + 1][j] = 1;
                }
            }
            else
            {
                for (int j = 1, f2 = 1; j <= m; j += 2, f2 ^= 1)
                {
                    if (f2 & 1)
                        map[i][j + 1] = map[i + 1][j] = 1;
                    else
                        map[i][j] = map[i + 1][j + 1] = 1;
                }
            }
        }
        for (int i = 1; i <= n; ++i, std::cout << "\n")
            for (int j = 1; j <= m; ++j, std::cout << " ")
                std::cout << map[i][j];
    }
    
    int main()
    {
        IOS;
        int t;
        std::cin >> t;
        while (t--)
            solve();
        return 0;
    }
    

    C - The Third Problem

    题意

    定义两个大小为 \(n\) 的排列 \(a,b\) 相似当且仅当:

    • 对于所有区间 \([l,r]\)\(MEX([a_l,a_{l+1}, \cdots ,a_r])=MEX([b_l,b_{l+1}, \cdots ,b_r])\)

    现给定排列 \(a\) ,求有多少个与之相似的排列 \(b\)

    题目分析

    首先玩样例,我们发现在 \(b\) 中,相对于 \(a\) ,有些数的位置是恒定不变的;有些数虽然会变,但可变的位置数也不尽相同。考虑 \(MEX\) 的性质,可以发现以下性质:

    • 如果 \(a\)\(i\) 在包含 \(0 \sim i-1\) 的最小区间中, 那么 \(b\)\(i\) 也应在包含 \(0 \sim i-1\) 的最小区间中
    • 如果 \(a\)\(i\) 在包含 \(0 \sim i-1\) 的最小区间外, 那么 \(b\)\(i\) 的位置理应与 \(a\) 中相同

    因此如果 \(i\) 在当前最小区间 \([l,r]\) 内,答案乘上 \((r-l+1)-p\) ,否则扩展当前最小区间。

    AC代码

    #include <bits/stdc++.h>
    #define IOS                           \
        std::ios::sync_with_stdio(false); \
        std::cin.tie(0);                  \
        std::cout.tie(0);
    using PII = std::pair<int, int>;
    using ll = long long;
    const int P = 1e9 + 7;
    
    ll solve()
    {
        int n;
        ll ans = 1;
        std::cin >> n;
        std::vector<int> a(n + 1), pos(n + 1);
        for (int i = 1; i <= n; ++i)
        {
            std::cin >> a[i];
            pos[a[i]] = i;
        }
        int l = std::min(pos[0], pos[1]), r = std::max(pos[0], pos[1]);
        for (int p = 2; p < n; ++p)
        {
            if (pos[p] < l || pos[p] > r)
                l > pos[p] ? l = pos[p] : r = pos[p];
            else
                ans = ans * (r - l - p + 1) % P;
        }
        return ans;
    }
    
    int main()
    {
        IOS;
        int t;
        std::cin >> t;
        while (t--)
            std::cout << solve() << "\n";
        return 0;
    }
    

    D. Almost Triple Deletions

    题意

    给你一个长度为 \(n\) 的数组 \(a\) ,你可以执行下列操作任意次:

    • 选择一个索引 \(i\) ,如果对该索引有 \(a_i \not = a_{i+1}\) ,则从数组中删除 \(a_i\)\(a_{i+1}\) ,并将数组的剩余部分串联起来

    例如,如果 \(a=[1,4,3,3,6,2]\) ,那么在进行 \(i=2\) 的操作后,所得数组将是 \([1,3,6,2]\)

    要求最后得到的数组中所有元素值相等,求其最大长度。

    题目分析

    赛时第一眼是DP,捣鼓半天发现不会d又转向贪心,结果贪不出来以为是构造,最后罚坐到结束也没什么好的思路。

    首先看下数据范围 \(n \leq 5000\) ,多半是个 \(O(n^2)\) 的算法。我们可以发现当一个长度为 \(n\) 的数组满足下列条件时,它可以被完全删除:

    • \(n\) 是偶数

    • \(a\) 中任意元素的出现次数至多为 \(n/2\)

    于是我们可以在 \(O(n^2)\) 的时间内计算出 \(a\) 的每个子数组是否可以被完全删除。

    \(f[i]\) 表示以 \(a_i\) 结尾的最终数组的最大长度,初始化当 \([1,i-1]\) 可被完全删除时 \(f[i] = 1\) ,否则 \(f[i] = 0\)

    转移有:

    \(f[i] = \max_{j=1}^{i-1}(f[j] + 1).(f[j] > 0 \enspace and \enspace a[i] = a[j] \enspace and \enspace [i+1,j-1] \enspace is \enspace deletable)\)

    考虑最终数组中尾部连续的一段 \(a_{j+1},\cdots,a_n\) 也是可能被完全删除的,因此我们需要d到 \(n+1\) ,并且 \(a_{n+1}\) 相当于万能通配符,那么答案即是 \(f[n+1]-1\) (要把 \(a_{n+1}\) 的长度减掉​)。

    看了下还有dalao用图论的方法做的,只能说我还是太菜了orz

    AC代码

    #include <bits/stdc++.h>
    #define IOS                           \
        std::ios::sync_with_stdio(false); \
        std::cin.tie(0);                  \
        std::cout.tie(0);
    
    int solve()
    {
        int n;
        std::cin >> n;
        std::vector<int> a(n + 1), cnt(n + 1);
        for (int i = 1; i <= n; ++i)
            std::cin >> a[i];
        std::vector<std::vector<int>> del(n + 1, std::vector<int>(n + 1));
        std::vector<int> f(n + 2);
        for (int i = 1; i <= n; ++i)
        {
            std::fill(cnt.begin(), cnt.end(), 0);
            for (int j = i, mx = 0; j <= n; ++j)
            {
                mx = std::max(mx, ++cnt[a[j]]);
                if ((j - i + 1) % 2 == 0 && mx <= (j - i + 1) / 2)
                    del[i][j] = 1;
            }
        }
        for (int i = 1; i <= n + 1; ++i)
            f[i] = del[1][i - 1];
        f[1] = 1;
        for (int i = 1; i <= n + 1; ++i)
            for (int j = 1; j <= i - 1; ++j)
                if (f[j] && (a[i] == a[j] || i == n + 1) && ((j + 1 > i - 1) || (del[j + 1][i - 1])))
                    f[i] = std::max(f[i], f[j] + 1);
        return f[n + 1] - 1;
    }
    
    int main()
    {
        IOS;
        int t;
        std::cin >> t;
        while (t--)
            std::cout << solve() << "\n";
        return 0;
    }
    
  • 相关阅读:
    Burpsuite intruder模块 越过token进行爆破,包含靶场搭建
    burpsuiteb windows10 下载与安装
    sqlmap的命令总结
    Vue.js与jQuery混用
    IE低版本cors跨域请求
    window.open打开网址被拦截
    一图一知之python3数据类型
    一图一知-vue强大的slot
    一图一知-强大的js数组
    windows中git输错密码后不能修改问题
  • 原文地址:https://www.cnblogs.com/Foreign/p/16449140.html
Copyright © 2020-2023  润新知