算法竞赛入门【码蹄集进阶塔335题】(MT2201-2225)
文章目录
- 算法竞赛入门【码蹄集进阶塔335题】(MT2201-2225)
- 前言
- 目录
-
- 1. MT2201 字符串转换
- 2. MT2202 Summer Pockets
- 3. MT2203 s的排列
- 4. MT2204 字母匹配
- 5. MT2205 数字重排
- 6. MT2206 萨卡兹人
- 7. MT2207 建立数据库
- 8. MT2208 雪色雪花余痕
- 9. MT2209 五彩斑斓的曙光
- 10. MT2210 回文串等级
- 11. MT2211 字符串构造
- 12. MT2212 密码
- 13. MT2213 最漂亮的工艺品
- 14. MT2214 天色天歌天籁音
- 15. MT2215 REFLECTION BLUE
- 16. MT2216 01操作
- 17. MT2217 进制查询
- 18. MT2218 永恒之2
- 19. MT2219 新十六进制
- 20. MT2220 人脑计算机
- 21. MT2221 8421码
- 22. MT2222 余3码
- 23. MT2223 二进制? 不同!
- 24. MT2224 二进制的排列
- 25. MT2225 36进制1
- 结语
前言

为什么突然想学算法了?
> 用较为“官方”的语言讲,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。
> 但从实际而言,是因为当下快到了考研和找工作的年纪(ಥ_ಥ),无论走哪一条路,都不免需要一些相对丰富的算法知识,是故,便产生了一个暑假速成算法的计划,可能对于像我这种算法竞赛小白而言,几乎很难,但我仍然还是想尝试一下,毕竟,梦想还是要有的,万一实现了呢?~( ̄▽ ̄~)~

为什么选择码蹄集作为刷题软件?
码蹄集,是在全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC) 指导下建设的,其依托全国各大名校计算机系和清华大学出版社等单位的强大资源,旨在为计算机学习爱好者提供全面和权威的计算机习题。
目录
1. MT2201 字符串转换
(1)题目描述
对于两个字符串A和B,需要找出最少的变换次数使得A与B一致。
每次变换可以选择如下三种操作的其中一种:
1.删除一个字符,
2.插入一个字符,
3.将一个字符改写为另一个字符。
格式
输入格式: 输入两行,每行一个非空字符串分别对应A和B,字符串仅由小写字母组成。
.
输出格式: 输出一个整数,代表将A变为B所需的最小操作次数。
样例1
输入:
asdfghjkl
ssdghjkl
.
输出: 2
备注:
字符串长度不超过2000。
(2)参考代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[2005][2005];
char a[2005], b[2005];
int main(){
scanf("%s", a+1); scanf("%s", b+1);
int len_a = strlen(a+1), len_b = strlen(b+1);
for (int j = 0; j <= len_b; j++) dp[0][j] = j;
for (int i = 0; i <= len_a; i++) dp[i][0] = i;
for (int i = 1; i <= len_a; i++) {
for (int j = 1; j <= len_b; j++) {
dp[i][j] = 0x3fffffff;
if (a[i] == b[j]) {
dp[i][j] = min(dp[i][j], dp[i-1][j-1]);
}
dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]);
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]);
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j-1]);
}
}
printf("%d\n", dp[len_a][len_b]);
return 0;
}
2. MT2202 Summer Pockets
(1)题目描述
小码妹是一个喜欢字符串的女孩子。
小码妹有一个长度为n 的字符串s 和一个大小为m 的字符集。
现在小码妹希望通过在s 两端增加或删去字符,使得s 变为一个回文串。但是增加或删去不同字符需要花费的代价不同。
小码妹希望花费最少的代价达成目标,于是她想寻求你的帮助。
格式
输入格式:
第一行输入一个整数n,n表示数据组数。
接下来n行,每行输入一个复数(以类似”a+bi”的格式输入,但不一定最简,可能会有多个项,输入的项的系数是浮点数)。
.
输出格式:
输出n行,按题目描述中“最简情况”输出读入得到的复数,浮点数用cout或printf( "%g”)输出。
样例1
输入:
第一行两个正整数m和n,分别表示字符集大小和s 的长度。
第二行为字符串s。
接下来 m行,每行由一个字符c (数据保证字符c唯一)和两个整数a, gy组成,之间用空格隔开,表示在s两端增加字符c需要α 的代价,删去字符c需要y的代价。
.
输出:
输出一个整数,表示将s 变为回文串需要的最小代价。
备注:
测试数据保证1≤m≤ 26, 1≤n ≤2000, 1≤a, y ≤10000且字符集为小写英文字母的子集。
(2)参考代码
#include<stdio.h>
#include <string.h>
#define min(x,y) (x)<(y)?(x):(y)
int dp[2005][2005];
int cost[30];
int main()
{
char str[2005];
int n,m,i,j;
scanf("%d %d %s",&n,&m,str);
char c;int add,del;
for(i=0;i<n;i++){
scanf(" %c %d %d",&c,&add,&del);
cost[c-'a']=min(add,del);
}
memset(dp,0,sizeof(dp));
for(j=1;j<m;j++)
for(i=j-1;i>=0;i--){
dp[i][j]=min(dp[i+1][j]+cost[str[i]-'a'],dp[i][j-1]+cost[str[j]-'a']);
if(str[i]==str[j])
dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
}
printf("%d\n",dp[0][m-1]);
return 0;
}
3. MT2203 s的排列
(1)题目描述
给两个字符串s1和s2,判断s2中是否有s1的排列。
如果是返回true ,否则返回false 。
s1的排列指的是s1字符的不同排列。
格式
输入格式:
第一行输入字符串s1
第二行输入字符串s2
.
输出格式: 输出小写的true或false
样例1
输入:
ab
eidbaooo
.
输出: true
(2)参考代码
// 编写一个判断子串的函数
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
bool checkInclusion(string s1, string s2) {
if(s1.size()>s2.size())return false; //剪枝,如果s1.size()>s2.size(),直接返回false;
vector<int>a1(26,0),a2(26,0); //申请两个容器;
for(int i=0;i<s1.size();i++){
a1[s1[i]-'a']++;
a2[s2[i]-'a']++; //把s1和s2装入容器中;
}
if(a1==a2)return true; //如果相等,直接返回true;
for(int i=s1.size(),j=0;i<s2.size();i++,j++){
//滑动窗口部分。
a2[s2[j]-'a']--;
a2[s2[i]-'a']++;
if(a1==a2)return true;
}
return false;
}
int main(){
string s1,s2;
cin>>s1;
cin>>s2;
if(checkInclusion(s1,s2)) printf("true");
else printf("false");
return 0;
}
4. MT2204 字母匹配
(1)题目描述
小码哥有一个字符串s。
现在他想请你判断有多少对(x , gy)满足s[c] =s[y]。其中x可以等于y。
注意(ac, y)和(g, z)是不相同的一对。
格式
输入格式:
第一行一个字符串S,长度小于等于1e5,包含ASClI码从33到125的所有字符。
.
输出格式: 按题目要求输出一行一个整数,表示(x,y)的对数。
样例1:
输入: greaat
.
输出:8
(2)参考代码
import time
from collections import deque, Counter
def main():
#code here
c = Counter(input())
tot=0
for v in c.values():
tot+=v**2
print(tot)
if __name__ == '__main__':
main();
5. MT2205 数字重排
(1)题目描述
给出n个数和m个字符串,字符串可以重复,而且重复的字符串视为一种字符串,同种字符串所代表的价值相同。
求把n个数分配给k种(注意,这里的k表示在这m个字符串中有k种不同类型的字符串,不过这个k是多少可能需要你自己去求)字符串得到的值的和最小价值和最大价值分别是多少(一个数只能分配一次)。
格式
输入格式:
输入第一行两个整数n, m (1 ≤m ≤100,1≤n ≤100000)。接下来一行n个数字,表示n个数(数字的范围均为1≤a≤1000 )。
接下来m行,分别表示m个字符串,保证每个字符串只含小写字母,长度不超过11且不含空格。
.
输出格式: 输出一行两个整数分别表示可以得到的最小值和最大值。
样例1
输入:
6 5
3 5 1 6 8 1
peach
grapefruit
banana
orange
orange
.
输出: 11 30
备注:
样例解释:
有4种字符串:
peach * 1;
grapefruit * 1;
banana * 1;
orange * 2。
最小值:取1,1,3,5,min = 12+11+31+51 = 11 ,
最大值:取8,6,5,3,maa =82+61+51+31 = 30。
(2)参考代码
#include <bits/stdc++.h>
using namespace std;
string a[105];
int n,m;
int b[100005],c[105],d[105];
int main()
{
cin>>n>>m;
int i,j,t,x=0,y=0;
for(i=0;i<n;i++) cin>>b[i];
sort(b,b+n);
for(i=0;i<m;i++) cin>>a[i];
for(i=0;i<m;i++) c[i]=1;
for(i=0;i<m&&(c[i]!=-1);i++)
{
for(j=i+1;j<m;j++)
{
if(a[j]==a[i])
{
c[i]++;
c[j]=-1;
}
}
}
j=0;
for(i=0;i<m;i++)
{
if(c[i]>0)
{
d[j]=c[i];
j++;
}
}
sort(d,d+j);
for(i=0,t=j-1;t>=0;i++,t--) x+=d[t]*b[i];
for(i=n-1,t=j-1;t>=0;i--,t--) y+=d[t]*b[i];
cout<<x<<" "<<y;
return 0;
}
6. MT2206 萨卡兹人
(1)题目描述
很久很久以前,卡西米尔里住着萨卡兹人,他们彼此争斗不休。有一天,他们想要研究自己的 DNA序列,来证明他们是一个种群。我们首先选取一个好长好长的序列(DNA序列包含26个小写英文字母),然后我们每次选择两个区间,这两个区间代表两个萨卡兹人的DNA序列,这两个萨卡兹一模一样的唯一可能是他们的DNA序列一模一样。
格式
输入格式:
第一行一个 DNA字符串S。
接下来一个数字m,表示 m次询问。
接下来 m行,每行四个数字l1, r1,l2,r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
.
输出格式: 对于每次询问,输出一行表示结果。如果两个萨卡兹完全相同输出Yes,否则输出No
样例1
输入:
aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2
.
输出:
Yes
No
Yes
备注:
提示
1.1<l≤r1 ≤length(S),1 ≤l≤r2≤length(S)
2.1≤length(S),m ≤ 1000000
(2)参考代码
#include <bits/stdc++.h>
#define ULL unsigned long long
using namespace std;
const int N=1e6+100;
ULL h[N],p[N];
char s[N];
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
int m;
scanf("%d",&m)

最低0.47元/天 解锁文章
8428

被折叠的 条评论
为什么被折叠?



