2021年第三届传智杯全国大学生IT技能大赛(决赛B组)

本文介绍了三道编程竞赛题目,涉及课程报名、和谐一对计算和字符串子串查找。第一题要求找出同时报名两个课程的学生数量,第二题需找出满足特定条件的数对数量,第三题则需计算字符串在另一个字符串中出现的次数。通过编程实现,解决实际问题。
摘要由CSDN通过智能技术生成

T172096 课程

题目背景

disangan233 喜欢数数,于是他想让你帮他回答一个问题。
题目描述

传智专修学院提供 A,B 两个课程,分别有 n,m个学生报名。报名 A 的学生的编号为 an​,报名 B 的学生的编号为 bm​,求有多少个学生同时报名了两个课程。

对于所有数据,n,m,ai,bi≤20,保证每个课程报名的学生编号不会重复。
输入格式

输入共 3 行。

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

第 2 行输入 n 个正整数 a1…an​,表示报名课程 A 的学生编号。

第 3 行输入 m 个正整数 b1…bm,表示报名课程 B 的学生编号。

学生编号不保证从小到大排序。
输出格式

输出共 1 行 1 个整数,表示答案。
输入输出样例
输入 #1

5 5
1 2 3 4 5
1 3 4 5 6

输出 #1

4

说明/提示
样例解释

我们发现,1,3,4,5 这 4 名学生同时报名了两门课程,所以答案是 4。

#include <iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
	int n,m,a[22],k,ans=0;
	cin>>n>>m;
	memset(a,0,sizeof(a));
	while(n--)
	{
		cin>>k;
		a[k]++;
	}
	while(m--)
	{
		cin>>k;
		a[k]++;
	}
	for(int i=0;i<22;i++)
	{
		if(a[i]==2)ans++;
	}
	cout<<ans<<endl;
	return 0; 
}

T172097 序列

题目背景

disangan333 喜欢 disangan233,于是他也想让你帮他数数。
题目描述

传智专修学院有 n 名同学,每个同学都有一个数字 an​。同时还知道一个常数 k 。

如果有两名同学,第 i 名同学和第 j 名同学,满足 i<j 且 ai×aj≤k,那么这两名同学就被称为“和谐的一对”。请问这些同学中,有多少对“和谐的一对”呢?

对于所有数据,n≤103,ai​≤105,k≤109。
输入格式

输入共 2 行。

第 1 行输入两个正整数 n,k。

第 2 行输入 n 个正整数 a1…an。
输出格式

输出共 1 行 1 个整数,表示答案。
输入输出样例
输入 #1

5 5
1 2 3 4 5

输出 #1

4

说明/提示
样例解释

样例中,(1,2),(1,3),(1,4),(1,5) 这 4 对都是“和谐的一对”。

#include <iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
	int n,k,a[1005],ans=0;
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			if(a[i]*a[j]<=k)ans++;
		}
	}
	cout<<ans<<endl;
	return 0; 
}

T172098 子串

题目背景

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

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

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

对于所有数据,T≤100,∑n≤∑m≤103。字符串仅由大小或者小写的英文字母组成。
输入格式

输入共 3T+1 行。

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

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

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

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

第 3 行输入一个长度为 m 的字符串 b。
输出格式

输出共 T 行,第 i 行输出 1 个整数,表示询问 i 的答案。
输入输出样例
输入 #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

#include <iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void c(string &s)
{
	for(int i=0;i<s.length();i++)
	{
		if(s[i]>='A'&&s[i]<='Z')
		{
			s[i]+='a'-'A';
		}
	}
}
int main()
{
	int t,n,m,ans=0;
	cin>>t;
	while(t--)
	{
		string a,b;
		cin>>n>>m;
		cin>>a>>b;
		c(a);
		c(b);
		for(int x,ls=b.length(),i=0;i<ls;i++)
        if((x=b.find(a,i))!=string::npos)
            ans++,i=x;
    cout<<ans<<endl;
	ans=0; 
	}
	return 0; 
}

T172099 打牌

题目背景

disangan233 想和 disangan333 一起打牌,并邀请了一起路过的你。
题目描述

三名同学在学习编程的休息时间(编号 1,2,3)打扑克,每人一开始 n 张牌,牌一共 m 种,若干张相同的牌可以一起出。

一开始由第一个人出,打出自己的牌里最小的牌。接下来,以玩家 1,2,3,1,2,3… 的顺序轮流出牌,每人打出一组比上个人打出的牌大的,自己能打出的最小的牌,若没有则跳过。

牌的大小是这么决定的:一组张数多的牌比张数少的牌大,如果张数同样多,那么点数大的牌比较大。例如,(1,1,1)>(3,3)>(2,2)>(4)>(1)。

若一轮中,其余两个人都无法打出牌,则重新下次由打出最后一张牌的人开始打。谁最先打完所有的牌,谁就赢了。请问最后谁会胜利呢?输出胜者的编号。

对于所有数据,n,m≤50。
输入格式

输入共 4 行。

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

第 2 到 4 行,每行输入 n 个数,表示每个人一开始的牌。
输出格式

输入共 1 行 1 个正整数,表示胜者的编号。
输入输出样例
输入 #1

10 3
1 3 3 1 3 3 1 2 3 3
3 2 1 2 2 3 3 1 1 2
2 2 1 2 3 1 2 3 3 1

输出 #1

3

说明/提示

样例中的玩法:

第 1 回合:
【1】:1 3 3 1 3 3 1 2 3 3,打出 [1]
【2】:3 2 1 2 2 3 3 1 1 2,打出 [2]
【3】;2 2 1 2 3 1 2 3 3 1,打出 [3]
【1】:3 3 1 3 3 1 2 3 3,打出 [1,1]
【2】:3 1 2 2 3 3 1 1 2,打出 [2,2]
【3】;2 2 1 2 1 2 3 3 1,打出 [3,3]
【1】:3 3 3 3 2 3 3,打出 [3,3,3]
【2】:3 1 3 3 1 1 2,出不起
【3】;2 2 1 2 1 2 1,打出 [2,2,2,2]
【1】:3 2 3 3,出不起
【2】:3 1 3 3 1 1 2,出不起

第 2 回合:
【3】;1 1 1,打出 [1]
【1】:3 2 3 3,打出 [2]
【2】:1 3 3 1 1 2,打出 [3]
【3】;1 1,打出 [1,1] <- 获胜

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define in inline
namespace fast_io
{
    char buf[1<<12],*p1=buf,*p2=buf,sr[1<<23],z[23],nc;int C=-1,Z=0,Bi=0,ny;
    in char gc() {return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<12,stdin),p1==p2)?EOF:*p1++;}
    in int read()
    {
        int x=0;ny=1;while(nc=gc(),(nc<48||nc>57)&&nc!=EOF)if(nc==45)ny=-1;Bi=1;if(nc<0)return nc;
        x=nc-48;while(nc=gc(),47<nc&&nc<58&&nc!=EOF)x=(x<<3)+(x<<1)+(nc^48),Bi++;return x*ny;
    }
    in db gf() {int a=read(),y=ny,b=(nc!='.')?0:read();return (b?a+(db)b/pow(10,Bi)*y:a);}
    in int gs(char *s) {char c,*t=s;while(c=gc(),c<=32);*s++=c;while(c=gc(),c>32)*s++=c;return s-t;}
    in void ot() {fwrite(sr,1,C+1,stdout);C=-1;}
    in void flush() {if(C>1<<22) ot();}
    template <typename T>
    in void write(T x,char t)
    {
        int y=0;if(x<0)y=1,x=-x;while(z[++Z]=x%10+48,x/=10);
        if(y)z[++Z]='-';while(sr[++C]=z[Z],--Z);sr[++C]=t;flush();
    }
    in void write(char *s) {int l=strlen(s);for(int i=0;i<l;i++)sr[++C]=*s++;sr[++C]='\n';flush();}
};
using namespace fast_io;
#define pii pair<int,int>
#define fi first
#define se second
const int N=1e3+5;
int n,m,a[4][N],c[4];
in pii ask(int x,pii y)
{
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) 
    if(a[x][j]>=i&&(i>y.fi||(i==y.fi&&j>y.se))) return a[x][j]-=i,c[x]-=i,make_pair(i,j);
    return {-1,-1};
}
int main()
{
    n=c[1]=c[2]=c[3]=read(),m=read();
    for(int i=1;i<=3;i++) for(int j=1;j<=n;j++) a[i][read()]++;
    for(int s=1,x,t;;s=t)
    {
        x=s,t=0;pii y={0,0};
        for(;x^t;x=x%3+1)
        {
            pii z=ask(x,y);
            if(!c[x]) return write(x,'\n'),ot(),0;
            if(~z.fi) t=x,y=z;
        }
    }
    return ot(),0;
}
//Author: disangan233

T172100 商店

题目背景

disangan333 想给 disangan233 买一个礼物,于是他和你一起逛商店。
题目描述

有 nnn 名同学去逛商店,店里有 m 个物品,第 i 人有 wi​ 块钱,第 i 个物品价格 ci​ 元。

每个人至多买一个物品,每个物品只能被买一次,问最多有多少人能买到物品。

对于所有数据,n,m≤105,wi,ci≤109w。
输入格式

输入共 3 行。

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

第 2 行输入 n 个整数 w1…wn​,wi​ 表示第 i 人的钱。

第 3 行输入 m 个整数 c1…cm​,ci 表示第 i 个物品的价格。
输出格式

对于所有数据,n,m≤105,wi,ci≤109。
输入输出样例
输入 #1

15 20
4 3 9 10 7 7 5 3 6 1 8 6 6 1 5
12 4 1 9 8 5 8 6 4 5 18 8 14 9 9 7 20 11 8 19

输出 #1

10

#include <iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
std::priority_queue<int, std::vector<int>, std::greater<int> > sp; //构造一个最小堆
using namespace std;
int main()
{
	int n,m,k,a[100005],ans=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=m;i++)
	{
		cin>>k;
		sp.push(k);
	}
	sort(a,a+n);
	k=0;
	while(k<=n)
	{
		if(a[k]>=sp.top())
		{
			sp.pop();
			k++;
			ans++;
		}
		else k++;
	}
	cout<<ans<<endl;
	return 0; 
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗蛋儿l

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值