Codeforces Round #804 (Div. 2) 题解

A. The Third Three Number Problem

题意

给你一个整数 n ,构造满足等式 (ab)+(bc)+(ac)=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

题意

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

题目分析

跟着样例画了画发现按 [1001][0110] 交替染色即可。

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([al,al+1,,ar])=MEX([bl,bl+1,,br])

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

题目分析

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

  • 如果 ai 在包含 0i1 的最小区间中, 那么 bi 也应在包含 0i1 的最小区间中
  • 如果 ai 在包含 0i1 的最小区间外, 那么 bi 的位置理应与 a 中相同

因此如果 i 在当前最小区间 [l,r] 内,答案乘上 (rl+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 ,如果对该索引有 aiai+1 ,则从数组中删除 aiai+1 ,并将数组的剩余部分串联起来

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

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

题目分析

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

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

  • n 是偶数

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

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

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

转移有:

f[i]=maxj=1i1(f[j]+1).(f[j]>0anda[i]=a[j]and[i+1,j1]isdeletable)

考虑最终数组中尾部连续的一段 aj+1,,an 也是可能被完全删除的,因此我们需要d到 n+1 ,并且 an+1 相当于万能通配符,那么答案即是 f[n+1]1 (要把 an+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;
}
posted @   FoXreign  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示