Codeforces题解

目录

C. Preparing for the Exam

题意分析:

算法思路:

源码实现:

B. Shohag Loves Strings

题意分析:

算法思路:

源码实现:

C. Superultra's Favorite Permutation

题意分析:

算法思路:

源码实现:

结语


引言

今天我们来打三个1000分的题目练练手,因为不在一个比赛中所以我就不具体写哪一场了,先看题目。

C. Preparing for the Exam

题目链接:Problem - 2051C - Codeforces

题意分析:

有 n 个不同问题,编号 1,2,…,n,有 m 个不同的“问题列表”,每个列表包含 恰好 n−1 个不同问题。第 i 个列表可以用一个整数 ai 表示,它表示这个列表中 唯一缺少的问题 的编号。

例如:n=4,ai=3 → 列表包含 {1,2,4}。

考试时,Monocarp 会拿到其中一个列表,他必须能回答该列表中 所有 问题才能通过。

Monocarp 事先知道 k 个问题的答案:q1,q2,…,qk​。

要求:对每个列表 i(即每个 ai​),判断他是否能通过。

算法思路:

关于判断他是否能通过我们可以这样想:

首先设 Monocarp 已知答案的问题集合为 Qknown={q1,q2,…,qk},然后设第 i 个列表包含的问题集合为:

S={1,2,…,n}∖{ai}(意思是除去第ai 个问题后所有问题的集合)。

因为 S 包含除了 ai 以外的所有 n−1个问题,所以:

1.如果 Qknown​ 包含所有 n 个问题,那么无论 ai​ 是什么,Monocarp 都能通过。

2.如果 Qknown​ 包含 n−1 个问题,那么只有当缺少的那个问题正好是 ai 时,Monocarp 才能通过(因为这样 S​ 正好等于 Qknown​)。

3.如果 Qknown​ 包含少于 n−1 个问题,那么 Monocarp 一定不能通过(因为 S 有 n−1 个问题,而 Monocarp 知道的问题数不够覆盖)。

所以我们可以用bool数组来确定已知问题编号的状态为true.

源码实现:

#include<iostream>
#include<vector>
using namespace std;
void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> a(m);
    vector<int> b(k);
    vector<bool> used(n + 1, false);
    for (int i = 0; i < m; i++)
    {
        cin >> a[i];
    }
    for (int i = 0; i < k; i++)
    {
        cin >> b[i];
    }
    for (int i = 0; i < k; i++)
    {
        used[b[i]] = true;
    }
    int op = k;
    for (int i = 0; i < m; i++)
    {
        if (op == n || op == n - 1 && !used[a[i]])
        {
            cout << "1";
        }
        else {
            cout << "0";
        }
    }
    cout << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 0;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

这道是div3的C题1000分,思维还是相对比较简单的。

B. Shohag Loves Strings

这个是1000分关于字符串问题的

题目链接:Problem - 2039B - Codeforces

我的这个插件翻译可能不太准确,可以的话最好跳转题目链接。

题意分析:

我们有一个字符串 s,要找一个它的非空子串 p,使得 f(p) 为偶数。

其中 f(p) 定义为 p 的非空子串的个数

题意还是比较简单的,思路我们需要分情况进行讨论。

算法思路:

若 p 的长度为 m,那么它的所有非空子串个数为:f(p)=(m*(m+1))/2,这是求非空子串的公式,因为要求f(p)为偶数,并且只需要输出任意一个解决方案,那这个问题我们就可以特殊化一下。

1.先找长度为 2 且两个字符相同的子串

一般的,当长度 m=2 时,f(p)=3 是奇数,不满足条件,但当两个字符相等时,比如:aa, f(p)==2满足条件

所以这种情况就是相邻相同字符,如果没有这样的相邻相同字符,就找长度为 3 且三个字符互不相同的子串

长度 m=3时,f(p)=6(偶数)

如果上述两种情况都不存在,输出 -1

源码实现:

#include<iostream>
#include<vector>
#include<string>
using namespace std;
void solve() {
    string s;
    cin >> s;
   
    for (int i = 0; i + 1 < s.length(); i++) {
        if (s[i] == s[i + 1]) {
            cout << s[i] << s[i + 1] << endl;
            return;
        }
    }

    for (int i = 0; i + 2 < s.length(); i++) {
        if (s[i] != s[i + 1] && s[i] != s[i + 2] && s[i + 1] != s[i + 2]) {
            cout << s.substr(i, 3) << endl;
            return;
        }
    }

    
    cout << -1 << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 0;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

特殊化处理还是比较简单的,我们需要注意的是aa这种情况。

C. Superultra's Favorite Permutation

题目链接:Problem - 2037C - Codeforces

这是一道1000分的数学思维题,不难,需要多观察一下。

题意分析:

我们需要构造一个长度为 n 的排列 p,使得对于任意相邻两项 pi+pi+1​ 都是合数

合数:大于 1 的非质数,即除了 1 和它本身之外还有其他因数。

算法思路:

由数学推论可知:所有大于 2 的偶数都是合数,并且任何两个奇偶性相同的数相加起来都是合数。现在我们就只需要找到一个奇数和一个偶数相加为一个合数,这样我们就可以将这两个数作为连接奇数和偶数的桥梁,我们可以验证 发现n≤4 中是没有这样的一对数,但是在 n=5 中存在 (4,5) ,它的和为 9 是一个合数。所以我们可以将奇数除了5之外都输出然后输出 5 4,再将偶数全部输出。

源码实现:

#include<iostream>
#include<vector>
#include<string>
using namespace std;
void solve() {
    int n;
    cin >> n;
    if (n < 5)
    {
        cout << -1 << endl;
        return;
    }
    for (int i = 1; i<= n; i+=2)
    {
       if(i!=5)
        cout << i << " ";
    }
    cout << "5 " << "4 " ;
    for (int i = 2; i <= n; i += 2)
    {
        
        if(i!=4)
            cout << i << " ";
    }
    cout << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 0;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

这道题还是很简单的数学思维。

结语

今天的任务到这就结束啦,希望上述题解对你们有帮助,谢谢观看呀,如果有什么问题或者错误欢迎在评论区指出,请大家多多关注,我会继续努力哒!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值