牛客CSP2020赛前模拟赛-第一天

得分100

题目解析

第一题

题目描述:

牛牛在注册不同的网站时,总是会使用不同的密码来保证他的账号安全。
为了保证他的密码强度,牛牛使用他的“字符串筛选器”来测试密码的强度。
具体来说,他先将输入的字符串筛选分成四部分。

第一部分仅由小写英文字母组成

第二部分仅由大写英文字母组成

第三部分仅由0到9的数字组成

第四部分由其余特殊字符组成

这四部分要保留它们在原字符串中的相对顺序。

比如将"1q2w3E4R5{6}"这个字符串进行筛选后

四部分分别为:"qw"、"ER"、"123456"、"{}"。

然后只要某一部分不为空,牛牛就认为他的密码等级高1级。
密码等级最低为1级,最高4级。
例如"asdA@123"的密码等级为4,"20020101"的密码等级为1。

请帮助牛牛判断他注册账号时的密码等级,以及该密码做字符串筛选后的结果。

解题思路:考察语言,直接模拟即可。

代码:

#include<bits/stdc++.h>
using namespace std;
string x[4], s;
int ans;
int main(){
    cin >> s;
    int len = s.length();
    for(int i = 0; i < len; i ++){
        if(s[i] <= 'z' && s[i] >= 'a'){
            x[0] += s[i];
            continue;
        }
        if(s[i] <= 'Z' && s[i] >= 'A'){
             x[1] += s[i];
            continue;
        }
        if(s[i] <= '9' && s[i] >= '0'){
            x[2] += s[i];
            continue;
        }
        x[3] += s[i];
    }
    for(int i = 0 ; i < 4; i ++){
        if(x[i].size()) ans ++;
        else x[i] = "(Null)";
    }
    printf("password level:%d\n", ans);
    for(int i = 0 ; i < 4; i ++){
        cout << x[i] << endl;
    }
    return 0;
}

第二题

题目链接

解题思路:

这道题是个贪心,考试的时候想用搜索来做(枚举每个点,然后向前和向后搜),结果写挂了。
看了题解,发现往回走是一个迷惑选项,只要一直往前(往右,即1 --> n + 1的方向)走就行了
在向右走的过程中更新一个能走到的最远的点的编号,和最近的能到达最远的点的编号(因为要维护字典序),如果当前走到的点就是最远能到达的点,说明不论怎样走都无法在往前,就是用魔法,使用魔法的点的编号就是最近的能到达最远的点的编号。如果最远能到达的点大于n,说明可以走到,结束输出就可以了。
这块有点绕,看代码就清楚了。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,num,minpos=1,maxdis=1,a[N],ans[N];
/*
num表示施展法术的数目;
minpos表示(两段施展法术之间区间的位置中)离最远能达到点最远的位置,即上述i位置;
maxdis表示(施展下一次法术之前)能达到的最远距离,即上述绿色位置;
ans[i]表示第i次施展法术的位置。
*/
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        if(a[i]){
            if(i+a[i]>maxdis){//如果能跳到的最远距离比记录的maxdis大
                maxdis=i+a[i];//刷新
                minpos=i;//记录下来能跳到最远距离对应的第一个位置,就是最靠左的位置
            }
        }
        else if(maxdis==i){//前面区间的位置最远也就到i(此i非上述i,而是循环遍历到的i)了,必须施展法术了
            ans[++num]=minpos;//把记录的最靠前的能一次到达最远距离的位置,加入答案中
            maxdis=i+1;//更新最远能到达的位置为i+1
            minpos=i+1;//更新最靠前能到达maxdis的位置为i+1
            //上面两步可以理解为“又回到最初的起点,记忆中你青涩的脸……”,就相当于又开辟了一段区间,而这段区间的左端点正是你上次施展法术后刚好到达的位置。略讲在另附中。
        }
        if(maxdis>n) break;
    }
    cout<<num<<endl;
    for(int i=1;i<=num;i++) cout<<ans[i]<<' ';
}

这个是题解的代码。
题解写的比我写的清楚:链接

第三题

目测是个并查集,考试的时候一直在写第二题,没来得及看。
正在研究,持续更新......

posted @ 2020-10-18 19:59  Lvlb2333  阅读(182)  评论(0编辑  收藏  举报