2022牛客寒假算法基础集训营3 ABCDEGIL
A. 智乃的Hello XXXX
随便输出Hello xxx即可。
B. 智乃买瓜
链接:https://ac.nowcoder.com/acm/contest/23478/B
来源:牛客网
题目描述
有一人前来买瓜。
“哥们儿,这瓜多少钱一斤呐”
“两块钱一斤”
“What's up,这瓜皮是金子做的,还是瓜粒子是金子做的”
智乃来到水果摊前买瓜,水果摊上贩卖着NN个不同的西瓜,第ii个西瓜的重量为wiwi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi22wi。
也就是说对于每个西瓜,智乃都有三种不同的决策:
- 购买一整个重量为wiwi的西瓜
- 把瓜劈开,购买半个重量为wi22wi的西瓜
- 不进行购买操作
为了简化题目,我们保证所有瓜的重量都是一个正偶数。
现在智乃想要知道,如果他想要购买西瓜的重量和分别为k=1,2,3...Mk=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对109+7109+7取余数后的结果。
输入描述:
第一行输入两个整数N,M(0≤N≤103,1≤M≤103)N,M(0≤N≤103,1≤M≤103),分别表示西瓜的数目NN,以及查询的重量上限为MM。
若NN不为00,接下来一行NN个正偶数wi(2≤wi≤2×103)wi(2≤wi≤2×103)表示每个西瓜的重量。
输出描述:
输出一行MM个数字,分别表示购买西瓜的重量和为k=1,2,3...Mk=1,2,3...M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对109+7109+7取余数后的结果。
示例1
输入
复制
3 6
8 2 4
输出
复制
1 2 1 3 2 3
比较裸的背包,dp[i, j]表示用前i个西瓜凑出j这个重量的方案数。需要注意的是dp数组第二维要开2e3,虽然m不超过1e3,但在代码中dp[i, w[i]] += 1;这一句涉及了wi,而wi可能达到2e3。转移方程见代码:
#include
#include
C. 智乃买瓜(another version)
链接:https://ac.nowcoder.com/acm/contest/23478/C
来源:牛客网
题目描述
本题是原*版*的另一个版本,简单来讲,本题是原版输入输出的倒置。
有一人前来买瓜。
“哥们儿,这瓜多少钱一斤呐”
“两块钱一斤”
“What's up,这瓜皮是金子做的,还是瓜粒子是金子做的”
智乃来到水果摊前买瓜,水果摊上贩卖着若干个不同的西瓜,第ii个西瓜的重量为wiwi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi22wi。
也就是说对于每个西瓜,智乃都有三种不同的决策:
- 购买一整个重量为wiwi的西瓜
- 把瓜劈开,购买半个重量为wi22wi的西瓜
- 不进行购买操作
为了简化题目,我们保证所有瓜的重量都是一个正偶数。
现在智乃知道,购买西瓜的重量和分别为k=1,2,3...Mk=1,2,3...M时,购买西瓜的方案的种类数对109+7109+7取余数后的结果。
她想要还原水果摊贩卖的这若干个不同的西瓜重量分别为多少,请你构造一个贩卖NN个不同西瓜的水果摊,其购买西瓜的重量和满足智乃的要求,当出现有多种符合题目描述的答案时,你只用输出任意一种。
我们保证输入的数据至少存在一个N≤103N≤103的合法解。
输入描述:
第一行输入一个正整数M(1≤M≤103)M(1≤M≤103),表示智乃所知购买西瓜质量和的上限。
接下来一行MM个整数,第ii个整数表示购买西瓜的重量和为ii时,购买西瓜的方案的种类数对109+7109+7取余数后的结果。
输出描述:
首先输出一个整数NN,西瓜的数目。要求你给出的NN大小范围在[0,103][0,103]之间
接下来一行NN个正偶数wiwi,表示每个每个西瓜的重量。要求你给出的wiwi大小范围在[2,2×103][2,2×103]之间,且wiwi为偶数。
输入数据保证,至少存在一组在输出范围内的合法解。
示例1
输入
复制
6
1 2 1 3 2 3
输出
复制
3
8 2 4
比赛时没有出思路,dp还是要多练~~~
首先容易知道2的个数是确定的。不放倒着考虑,在B题中dp[i, j]的方案数是怎么得到的,这里就怎么减去。思路就是在把一个个dp方案数变为0的过程中不断将使用的重量放到答案vector中。从前往后遍历dp数组,如果一个位置的值不为0,说明这些剩下的这个重量i对应的方案数只能由i*2这个西瓜/2来提供。此时就把一个i*2放入ans,然后更新后面的dp数组部分。
#include
#include
D. 智乃的01串打乱
纯签,随便选两个01位置交换即可。
E. 智乃的数字积木
链接:https://ac.nowcoder.com/acm/contest/23478/E
来源:牛客网
题目描述
本题有对应的hard version,两者的区别仅在数据范围,保证easy version的测试用例集是hard version的子集。
智乃酱有NN块积木,每一块积木都有自己的颜色以及数字,这NN块积木颜色的范围从11到MM,数字的范围从00到99。
现在智乃酱把这些积木从左到右排成一排,这样积木看上去就形成了一个大整数,智乃觉得这个数字不够大,所以他决定交换一些积木使得这个大整数尽可能的大。
具体来讲,智乃可以在任意时刻无限次的交换相邻且同色的数字积木。
但是即使这样,智乃觉得这个数字还是不够大。
所以智乃酱拿出了她的油漆桶,她决定进行KK次操作,每次操作都选中两种颜色PP,QQ,然后将所有颜色为PP的积木染成颜色QQ。
当然,在染色结束后智乃酱也是可以交换相邻同色积木进行调整。
现在智乃想要知道,她进行KK次染色操作之前,以及每次染色后能够通过交换得到最大的正整数是多少,当然啦,这个大整数被允许包含前导零。
因为这个大整数很大,所以只要求你输出答案对109+7109+7取余数的结果即可。
输入描述:
第一行输入三个整数N,M,K(1≤N,M≤105,0≤K≤10)N,M,K(1≤N,M≤105,0≤K≤10)分别表示积木的数目,初始颜色的种类,以及智乃酱染色的次数。
接下来输入一个长度为NN的字符串,字符串仅由数字0?90?9组成。
接下来一行NN个正整数coli(1≤coli≤M)coli(1≤coli≤M)表示积木的颜色。
接下来KK行,每行输入两个正整数P,Q(1≤P,Q≤M)P,Q(1≤P,Q≤M)表示选中两种颜色PP,QQ,然后将所有颜色为PP的积木染成颜色QQ。
输出描述:
输出K+1K+1行,即她进行KK次染色操作之前,以及每次染色后能够通过交换得到最大的正整数对109+7109+7取余数的结果。
示例1
输入
复制
10 2 0
9586547120
1 2 1 2 1 1 1 1 1 1
输出
复制
586754147
示例2
输入
复制
10 2 1
9586547120
1 2 1 2 1 1 1 1 1 1
1 2
输出
复制
586754147
876554147
示例3
输入
复制
5 5 4
12345
1 2 3 4 5
3 2
2 5
4 5
5 1
输出
复制
12345
13245
13245
15432
54321
注意到k范围很小,因此每次染色直接暴力处理,然后对于同色的区间暴力排序,再暴力遍历计算字符串的值即可。
#include
#include
G. 智乃的树旋转
链接:https://ac.nowcoder.com/acm/contest/23478/G
来源:牛客网
题目描述
本题有对应的hard version, *easy version有额外的限制条件*,保证easy version的测试用例集是hard version的子集。
树旋转是在二叉树中的一种子树调整操作, 每一次旋转并不影响对该二叉树进行中序遍历的结果。
树旋转通常应用于需要调整树的局部平衡性的场合。树旋转包括两个不同的方式,分别是左旋和右旋。 两种旋转呈镜像,而且互为逆操作。
如图所示,为树的左旋转和右旋转示意图。当AA节点位于BB节点的左子树时,可以进行以AA节点为旋转轴的右旋转,反之可以进行以BB节点为旋转轴的左旋转。
具体来讲
右旋转:
当节点AA位于节点BB的左孩子时,节点AA可作为旋转轴进行右旋转,该旋转操作涉及到结构改变的节点有44个。
我们记旋转前AA节点的右孩子为ββ节点,BB节点的父节点为XX节点(若BB节点就是整棵树的根节点,则无需做与XX节点相关的操作)。
则旋转后ββ节点由AA节点的右孩子变为BB节点的左孩子,XX节点的其中一个孩子节点由BB节点改变为AA节点,并且它们和XX节点的中序顺序不发生其他变化;也就是说原来BB节点是XX节点的右孩子,则旋转后变为AA节点替换BB节点成为XX节点新的右孩子,反之若BB节点初始是XX节点的左孩子,则旋转后AA节点替换BB节点成为XX节点新的左孩子。
左旋转:
当节点BB位于节点AA的右孩子时,节点BB可作为旋转轴进行左旋转,该旋转操作涉及到结构改变的节点有44个。
我们记旋转前BB节点的左孩子为ββ节点,AA节点的父节点为XX节点(若AA节点就是整棵树的根节点,则无需做与XX节点相关的操作)。
则旋转后ββ节点由BB节点的左孩子变为AA节点的右孩子,XX节点的其中一个孩子节点由AA节点改变为BB节点,并且它们和XX节点的中序顺序不发生其他变化;也就是说原来AA节点是XX节点的右孩子,则旋转后变为BB节点替换AA节点成为XX节点新的右孩子,反之若AA节点初始是XX节点的左孩子,则旋转后BB节点替换AA节点成为XX节点新的左孩子。
智乃最近学习了树旋转,树旋转的本质是二叉树旋转轴节点与其父节点父子关系的改变,从视觉效果上看起来好像整个树进行了“旋转”。
在实际的操作过程中,如果指定旋转轴,其实就没有所谓“左旋转”和“右旋转”的区别,当旋转轴确定时,将只有一种旋转方法,遵循以下规则。
- 根节点无法作为旋转轴被选定。
- 当旋转轴是其父节点的左子树时,旋转轴只能进行右旋转。
- 当旋转轴是其父节点的右子树时,旋转轴只能进行左旋转。
现在智乃有一颗尺寸大小为NN二叉树,智乃对其做了一次旋转操作将其打乱,她想让你通过一系列树的旋转操作将其还原,要求你的操作次数不多于N2N2次。
输入描述:
第一行输入一个正整数N(1≤N≤103)N(1≤N≤103),表示二叉树的节点数目,节点从11到NN标号。
接下来NN行输入二叉树一开始的样子。
每行输入两个非负整数lch,rch(0≤lch,rch≤N)lch,rch(0≤lch,rch≤N)表示每个节点的左右子树。
当lchlch的值为00时,则表示该节点无左子树,当rchrch的值为00时,则表示该节点无右子树。
接下来NN行输入二叉树被打乱后的样子。
每行输入两个非负整数lch,rch(0≤lch,rch≤N)lch,rch(0≤lch,rch≤N)表示每个节点的左右子树。
当lchlch的值为00时,则表示该节点无左子树,当rchrch的值为00时,则表示该节点无右子树。
要求你将打乱后的二叉树通过一系列旋转操作还原
输出描述:
首先输出一个整数KK,表示你还原二叉树进行旋转的次数,要求你给出KK的范围在[0,N2][0,N2],接下来KK行,依次输出旋转操作的旋转轴。
由于旋转轴只能进行左旋转或者右旋转其中的一种,裁判程序将会自己判断当前需要进行的是左旋转还是右旋转。
注意:旋转过程中的根节点无法作为旋转轴进行旋转,如果你指定旋转过程中的根节点作为旋转轴,则裁判程序将直接给出WA的结果。
easy version额外限制条件,保证可以通过不多于一次树旋转的操作还原二叉树,即一定存在K≤1K≤1的解。
示例1
输入
复制
5
2 3
0 0
4 5
0 0
0 0
2 4
0 0
1 5
0 0
0 0
输出
复制
1
1
easy version比较简单,因为最多只旋转一次,因此旋转的只能是前后两棵树之间父子关系互换的两个点。
#include
#include
I. 智乃的密码
链接:https://ac.nowcoder.com/acm/contest/23478/I
来源:牛客网
题目描述
智乃去注册账号,他发现网站的的密码必须符合以下几个条件
- 密码是仅包含大小写英文字母、数字、特殊符号的字符串。
- 密码的长度不少于LL个字符,并且不多于RR个字符。
- 密码中应该至少包括①大写英文字母、②小写英文字母、③数字、④特殊符号这四类字符中的三种。
所谓特殊字符,是指非大小写字母、数字以及空格回车等不可见字符的可见字符,包括但不限于"~!@#$%^&*()_+"。
现在智乃有一个长度大小为NN的字符串SS,她想知道SS串中有多少个子串是一个符合条件的密码,请你帮助智乃统计符合条件的密码数目。
子串是指字符串中某一段连续的区间,例如对于字符串"abcde"来说,"abc","cde"都是它的子串,而"ace"不是它的子串。
输入描述:
第一行输入三个正整数N,L,R(1≤N≤105,1≤L≤R≤N)N,L,R(1≤N≤105,1≤L≤R≤N),表示SS串的长度,合法密码长度应该在LL到RR个字符之间。
接下来一行输入一个长度为NN的字符串SS,字符串仅包括①大写英文字母、②小写英文字母、③数字、④特殊符号四类字符。
输出描述:
仅一行一个整数,表示有多少子串是一个合法的密码。
示例1
输入
复制
10 6 8
asdfeg111*
输出
复制
3
说明
"eg111*","feg111*","dfeg111*"
这个题双指针或二分都可以做,比赛时写了半天错的双指针改不出来,没办法只能二分了...
二分时遍历每个可能的右端点,二分的是实际区间右端点到左端点的距离(因为距离小的时候满足,则距离大的时候一定满足,解满足单调性),判断区间是否合法可以用前缀和。举例来说,设有区间1 2 3 4 5 6,L = 3, R = 6, 如果[1 2 3 4]合法,那么[1 2 3 4 5]和[1 2 3 4 5 6]肯定都合法。
注意左端点不会超过1!一定要特别处理!代码比较抽象,简单参考一下吧~
#include
#include
L. 智乃的数据库
链接:https://ac.nowcoder.com/acm/contest/23478/L
来源:牛客网
题目描述
智乃最近在学习数据库的查询语言SQL。SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统(RDBMS)。 SQL 的范围包括数据插入、查询、更新和删除,数据库模式创建和修改,以及数据访问控制。
使用SQL,可以灵活的对数据库表进行操作,在数据库的查询语句中有"GROUP BY"这样一种关键字。
GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。
例如数据库中储存了这样一个数据库表Table,执行带有"GROUP BY"关键字的查询语句。
id name val 1 chino 1 2 chino
2 3 kokoa
3 SELECT COUNT(*) FROM Table GROUP BY name;
SQL语句中COUNT表示聚合后每一个组中有多少条数据。
当执行上述的SQL查询语句后,其返回的结果如下
2 2 1
第一行的2表示按照name字段进行分组聚合,一共可以分出2组。
第二行的两个整数表示每组中各有多少条数据。
当然了,"GROUP BY"关键字是可以选中多个列进行分组聚合的,只需要把这些字段用逗号隔开即可。
SELECT COUNT(*) FROM Table GROUP BY name,val;
例如这样的SQL查询语句,执行后返回的结果如下
3 1 1 1
现在智乃把这张数据库表导出给你,请你执行一个SELECT COUNT(*) FROM Table GROUP BY ...;的查询语句,请你把查询的结果告诉智乃。
为了简化问题,我们假设数据库的表由NN条记录以及MM个字段组成,且这些字段的类型均为int类型。
输入描述:
第一行输入两个正整数N,M(1≤N,M≤1000)N,M(1≤N,M≤1000),表示数据库表中有NN条记录以及MM个字段。
接下来一行输入MM个字符串Si(1≤∣Si∣≤50)Si(1≤∣Si∣≤50)表示每个字段的名称。
接下来NN行,每行MM列,输入一个二维表格datai,j(0≤datai,j≤109)datai,j(0≤datai,j≤109)表示数据库表中第ii条记录的第jj个字段的值。
接下来输入一行一个字符串SQL(1≤∣SQL∣≤5×104)SQL(1≤∣SQL∣≤5×104),表示查询语句,查询语句的格式为"SELECT????COUNT(?)????FROM????Table????GROUP????BY????...;""SELECTCOUNT(?)FROMTableGROUPBY...;"。
其中"...""..."是若干个字段名称,保证是之前输入的MM个字段中的某些字段,且这若干个字段互不相同,字段与字段之间用一个逗号隔开。
输出描述:
第一行输出一个整数KK表示聚合后组的数目。
接下来一行输出KK个整数,表示每组中聚合的记录数目,整数与整数之间用空格隔开。
你可以按照你喜欢的顺序输出答案,裁判程序将忽略输出顺序的影响。
示例1
输入
复制
4 3
id name val
1 1 2
1 1 3
1 2 1
2 2 2
SELECT COUNT(*) FROM Table GROUP BY name,id;
输出
复制
3
1 2 1
模拟题。思路就是按这若干个字段进行排序,然后相邻的这若干个字段值相同的分到一组即可。
#include
#include