【传智杯】子串、志愿者、面试题解

博客主页:@披星戴月的贾维斯
欢迎关注:点赞收藏留言
系列专栏: 蓝桥杯
请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信,世界上总有一些美好值得我们全力以赴,哪怕粉身碎骨!
一起加油,去追寻、去成为更好的自己!

文章目录

  • 1、# [传智杯 #3 决赛] 子串
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 分析题意:
  • 2、# [传智杯 #3 初赛] 志愿者
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 分析题意:
  • 3、[传智杯 #3 决赛] 面试
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 样例解释
      • 分析题意:
  • 总结

提示:以下是本篇文章正文内容,下面案例可供参考


    这次我们继续和大家分享一些传智杯题解,多刷题对我们来说是一件非常重要的事,坚持下去会有很多收获!

1、# [传智杯 #3 决赛] 子串

题目背景

disangan233 喜欢字符串,于是 disangan333 想让你找一些 disangan233 喜欢的串。

题目描述

在传智的开发课堂上,希望您开发一款文档处理软件。

给定 T T T 组询问,每次给定 2 2 2 个长度为 n , m n,m n,m 的只含英文字母的字符串 a , b a,b a,b,求 a a a b b b 中的出现次数,相同字符不区分大小写。注意 a a a b b b 中连续子序列。

对于所有数据, T ≤ 100 T\leq 100 T100 ∑ n ≤ ∑ m ≤ 1 0 3 \sum n\leq \sum m\leq 10^3 nm103。字符串仅由大小或者小写的英文字母组成。

输入格式

输入共 3 T + 1 3T+1 3T+1 行。

1 1 1 行输入 1 1 1 个正整数 T T T

接下来共 T T T 组输入,每组输入共 3 3 3 行。

1 1 1 行输入 2 2 2 个正整数 n , m n,m n,m

2 2 2 行输入一个长度为 n n n 的字符串 a a a

3 3 3 行输入一个长度为 m m m 的字符串 b b b

输出格式

输出共 T T T 行,第 i i i 行输出 1 1 1 个整数,表示询问 i i i 的答案。

样例 #1

样例输入 #1

5
3 10
abc
abcabcabca
2 10
aa
AAaAaaAaAa
5 5
AbCdE
eDcBa
5 5
abcde
ABCDE
3 10
aba
ABaBaAbaBA

样例输出 #1

3
9
0
1
4

提示

对于第一组输入,出现了 3 3 3 次,分别是 [abc]abcabcaabc[abc]abcaabcabc[abc]a

对于第二组输入,出现了 9 9 9 次,分别是 [Aa]AaaAaAaA[aA]aaAaAaAa[Aa]aAaAaAaA[aa]AaAaAaAa[aA]aAaAaAaa[Aa]AaAaAaaA[aA]aAaAaaA[aA]aAaAaaAa[Aa]

分析题意:

首先,题目的意思是让我们子串,注意:不区分大小写,所以我们可以先把原字符串中本来是大写的字符通过加上32后,就变成了对应的小写字母,这时候我们再来找子串,我们for循环原串,如果找到首字母是子串的,我们就先创建一个临时字符串,如果这个字符串等于子串,答案++。
C++代码示例:

#include
using namespace std;

int t;
void fun(string &s) //这里的形参用引用,导致main函数的原串也会改变
{
    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] >= 'A' && s[i] <= 'Z') s[i] +=32;
    }
}

int main ()
{
    cin >> t;//表示有几组
    
    while(t --)
    {
        int n, m;//分别表示子串和原串的长度
        cin >> n >> m;
        string s1, s2;
        cin >> s1 >> s2;
        fun(s1);
        fun(s2);
        int ans = 0;
        for(int i = 0; i < m; i++) //for循环原串
        {
            string s;//临时字符串
            if(s2[i] == s1[0])
            {
                for(int j = i; j < i + n; j++)
                    s += s2[j];
                if(s == s1)
                {
                    ans ++;
                }
            }
            
        }
        cout << ans << endl;
    }
    return 0;
}

2、# [传智杯 #3 初赛] 志愿者

题目描述

传智专修学院总共召集了 n n n 位志愿者来负责打扫活动,现在需要你负责帮忙统计每位志愿者的工作情况,用来制作光荣榜,给他们发小花花。

i i i 位志愿者有一个工作时长 t i t_i ti ,以及他负责的工作的难度系数 k i k_i ki ,一名志愿者的贡献度可以用 k i × t i k_i \times t_i ki×ti 确定。

现在要为这些志愿者的贡献度从大到小排个序,请你完成这个任务。相同贡献度的志愿者以工作时长较长的排在前面。如果贡献和时长一样,那么编号小的志愿者排在前面。

输入格式

一行一个整数 n n n ,表示志愿者的数量。

接下来 n n n 行,每行两个使用空格隔开的整数 t i , k i t_i,k_i ti,ki ,表示第 i i i 名志愿者的时间和难度系数。

输出格式

一行,共 n n n 个整数,第 i i i 个数表示排名为 i i i 的志愿者的序号,从 1 1 1 开始编号。

请注意本题时限为 5s,输入输出规模较大,请注意常数因素对耗时的影响,我们不会给使用 Java 和 Python 的选手增加额外的运行时间。

样例 #1

样例输入 #1

3
1 2
2 3
3 4

样例输出 #1

3 2 1

提示

对于 40 % 40\% 40% 的数据,满足 1 ≤ n ≤ 100 1 \leq n \leq 100 1n100
对于额外 20 % 20\% 20% 的数据,满足 k i = 1 k_i=1 ki=1
对于 100 % 100\% 100% 的数据,满足 1 ≤ n ≤ 5 × 1 0 5 , 1 ≤ k i , t i ≤ 1000 1 \leq n \leq 5 \times 10^5,1 \leq k_i,t_i \leq 1000 1n5×105,1ki,ti1000

然而,由于本次比赛是 ACM 赛制,因此您必须通过 100 % 100\% 100% 的数据才能够获得本题的得分,后题同。

分析题意:

题目很明显就是让我们用一种方式去排序数据,然后输出,通过审题,我们发现这组数据有三个属性,首先,序号,其次是工作难度k和时间t, 所以我们只需要建立一个员工结构体,把数据全部输进去,然后根据题目要求排序sort,然后输出即可。

C++代码示例:

#include
using namespace std;

const int N = 5e5 + 10;

int n;
int c[N];
struct zyz
{
     int h; //号数
     int s;//时长
     int nd; //难度
};
struct zyz a[N]; //设置结构体数组

bool cmp(const zyz&z1, const zyz &z2)
{
    int val1 = z1.s * z1.nd;
    int val2 = z2.s * z2.nd;
    //如果贡献度相同,序号先的先输出
    if(val1 == val2)
    {
        if(z1.s == z2.s) return z1.h < z2.h;//号数小的放前面
        else return z1.s > z2.s; //时长长的先输出
    }
    else return val1 > val2; //否则按照贡献度来排序
}

int main ()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        int t, k;
        cin >> t >> k;
        a[i].h = i;
        a[i].s = t;
        a[i].nd = k;
    }
    sort(a + 1, a + n + 1, cmp);
    
    for(int i=1;i<=n;i++)
    {
        cout << a[i].h << " ";
    }
    return 0;
}

3、[传智杯 #3 决赛] 面试

题目背景

disangan233 和 disangan333 去面试了,面试官给了一个问题,热心的你能帮帮他们吗?

题目描述

现在有 n n n 个服务器,服务器 i i i 最多能处理 a i a_i ai 大小的数据。

接下来会有 k k k 条指令 b k b_k bk,指令 i i i 表示发送 b i b_i bi 的数据,需要你分配一个空闲的服务器。

请你算出一个序列 p k p_k pk 表示指令 i i i 的数据分配给服务器 p i p_i pi,且 p k p_k pk 的字典序最小;如果无法分配,输出 “-1”。

对于所有数据, n , k ≤ 6 n,k\leq 6 n,k6 a i , b i ≤ 10 a_i,b_i \leq 10 ai,bi10

输入格式

输入共 3 3 3 行。

1 1 1 行输入 2 2 2 个正整数 n , k n,k n,k

2 2 2 行输入 n n n 个正整数 a i a_i ai,表示服务器 i i i 最多能处理的数据大小。

3 3 3 行输入 k k k 个正整数 b i b_i bi,表示指令 i i i

输出格式

输出共 1 1 1 k k k 个正整数 p 1 … p k p_1\ldots p_k p1pk,或者输出 “-1”。

样例 #1

样例输入 #1

6 6
1 9 1 9 8 1
1 1 4 5 1 4

样例输出 #1

1 3 2 4 6 5

提示

样例解释

第 1 条指令分给服务器 1;
第 2 条指令分给服务器 3;
第 3 条指令分给服务器 2;
第 4 条指令分给服务器 4;
第 5 条指令分给服务器 6;
第 6 条指令分给服务器 5。

分析题意:

首先,我们通过数据量来分析这一题要考的算法, 由于数据量都非常小,都在10以内,因此可以考虑爆搜,dfs, 或者简单的背包等算法。通过审题,我们容易发现这题可以用dfs求解,找服务器能够运行的指令。
C++代码示例:

#include
using namespace std;

const int N = 10;
int a[N], b[N], ans[N];
int n, k;
bool flag = true, st[N];

void dfs(int u) //u表示现在枚举到了第几个
{
    if(u > k)//就说明所有的都枚举完了
    {
        if(flag)
        {
            for(int i = 1; i <= k; i++)
            cout << ans[i] << " ";
        }
        flag = false;
        return;
    }
    for(int i = 1; i <= n; i++)
    {
        if(a[i] -b[u] >= 0 && !st[i]) //如果这台机器没被选过&&服务器能处理这些数据 
        {
            ans[u] = i;
            st[i] = true;
            dfs(u + 1);
            st[i] = false;
        }
    }
    return;
}

int main ()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    
    for(int j = 1; j <= k; j++) cin >> b[i];
    dfs(1);
    if(flag) //找不到就输出-1
    puts("-1");
    
    return 0;
}

总结

    这次和大家分享了传智杯的几题普及/普及+难度的题,希望大家读后能有所收获!

你可能感兴趣的:(蓝桥杯,算法手札,算法,c++)