蓝桥杯题集
题目链接
acwing蓝桥杯
1.错误票据
难度:简单
时/空限制:1s / 64MB
来源:第四届蓝桥杯省赛C++A/B组,第四届蓝桥杯省赛JAVAA/B组
题目描述
某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。
全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
输入格式
第一行包含整数 \(N\),表示后面共有 \(N\) 行数据。
接下来 \(N\) 行,每行包含空格分开的若干个(不大于100个)正整数(不大于100000),每个整数代表一个ID号。
输出格式
要求程序输出1行,含两个整数 \(m,n\),用空格分隔。
其中,\(m\)表示断号ID,\(n\)表示重号ID。
数据范围
\(1≤N≤100\)
输入样例:
2
5 6 8 11 9
10 12 9
输出样例:
7 9
解题思路
模拟
数据较小,用数组下标标记,模拟一遍即可~ 关键在于字符串的处理~
- 时间复杂度:\(O(n)\)
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
int mn=0x3f3f3f3f,mx=0;
int v[100010],x;
int main()
{
int n;
memset(v,0,sizeof v);
scanf("%d",&n);
getchar();
while(n--)
{
string s;
stringstream ss;
getline(cin,s);
ss.str(s);
while(ss>>x)
{
v[x]++;
mx=max(mx,x);
mn=min(mn,x);
}
}
int r1,r2;
for(int i=mn;i<=mx;i++)
if(v[i]==0)r1=i;
else if(v[i]==2)r2=i;
printf("%d %d",r1,r2);
return 0;
}
2.买不到的数目
难度:简单
时/空限制:1s / 64MB
来源:第四届蓝桥杯省赛C++A组,第四届蓝桥杯省赛JAVAC组
题目描述
小明开了一家糖果店。
他别出心裁:把水果糖包成4颗一包和7颗一包的两种。
糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。
当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。
大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数 \(n,m\),表示每种包装中糖的颗数。
输出格式
一个正整数,表示最大不能买到的糖数。
数据范围
\(2≤n,m≤1000\),
保证数据一定有解。
输入样例:
4 7
输出样例:
17
解题思路
如果 \(a,b\) 均是正整数且互质,那么由 \(ax+by,x≥0,y≥0\) 不能凑出的最大数是 \(ab−a−b\)。
- 时间复杂度:\(O(1)\)
代码
#include<cstdio>
using namespace std;
int n,m;
int main()
{
scanf("%d %d",&n,&m);
printf("%d",n*m-n-m);
return 0;
}
3.剪格子
难度:困难
时/空限制:1s / 64MB
来源:第四届蓝桥杯省赛C++A/C组,第四届蓝桥杯省赛JAVAA/C组
题目描述
如下图所示,\(3×3\) 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是 60。
本题的要求就是请你编程判定:对给定的 \(m×n\) 的格子中的整数,是否可以分割为两个连通的部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0。
输入格式
第一行包含两个整数 \(m,n\) ,表示表格的宽度和高度。
接下来是 \(n\) 行,每行 \(m\) 个正整数,用空格分开。
输出格式
在所有解中,包含左上角的分割区可能包含的最小的格子数目。
如果无法分割,则输出 \(0\)。
数据范围
\(1≤n,m<10\),
格子内的数均在1到10000之间。
输入样例1:
3 3
10 1 52
20 30 1
1 2 3
输出样例1:
3
输入样例2:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
输出样例2:
10
解题思路
dfs,剪枝,字符串hash,并查集
- 时间复杂度:\(()\)
代码
4.大臣的旅费
难度:中等
时/空限制:1s / 64MB
来源:第四届蓝桥杯省赛C++A组,第四届蓝桥杯省赛JAVAA组
题目描述
很久以前,T王国空前繁荣。
为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。
同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。
所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。
他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数 \(n\),表示包括首都在内的T王国的城市数。
城市从 \(1\) 开始依次编号,\(1\) 号城市为首都。
接下来 \(n−1\) 行,描述T国的高速路(T国的高速路一定是 \(n−1\) 条)。
每行三个整数 \(P_i,Q_i,D_i\),表示城市 \(P_i\) 和城市 \(Q_i\) 之间有一条双向高速路,长度为 \(D_i\) 千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
数据范围
\(1≤n≤10^5, 1≤P_i,Qi_≤n, 1≤D_i≤1000\)
输入样例:
5
1 2 2
1 3 1
2 4 5
2 5 4
输出样例:
135
树的直径
代码
5.翻硬币
难度:简单
时/空限制:1s / 64MB
来源:第四届蓝桥杯省赛C++B组
题目描述
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:**oo***oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作。
输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。
输出格式
一个整数,表示最小操作步数
数据范围
输入字符串的长度均不超过100。
数据保证答案一定有解。
输入样例1:
**********
o****o****
输出样例1:
5
输入样例2:
*o**o***o***
*o***o**o***
输出样例2:
1
解题思路
递推
对每个数进行翻转是独立的,相互之间不会影响,且每个数的翻转不会超过1次,从第一个数是否翻转递推即可~
- 时间复杂度:\(O(n)\)
代码
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string a,b;
cin>>a>>b;
int res=0;
for(int i=0;i<a.size()-1;i++)
if(a[i]!=b[i])
{
res++;
if(a[i+1]=='*')a[i+1]='o';
else
a[i+1]='*';
}
cout<<res;
return 0;
}
6.带分数
题目描述
\(100\) 可以表示为带分数的形式:\(100=3+69258714\)
还可以表示为:\(100=82+3546197\)
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。
类似这样的带分数,\(100\) 有 \(11\) 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。
数据范围
\(1≤N<10^6\)
输入样例1:
100
输出样例1:
11
输入样例2:
10^5
输出样例2:
6
解题思路
代码
7.连号区间数
小明这些天一直在思考这样一个奇怪而有趣的问题:
在 1∼N 的某个排列中有多少个连号区间呢?
这里所说的连号区间的定义是:
如果区间 \([L,R]\) 里的所有元素(即此排列的第 L 个到第 R 个元素)递增排序后能得到一个长度为 \(R−L+1\) 的“连续”数列,则称这个区间连号区间。
当 \(N\) 很小的时候,小明可以很快地算出答案,但是当 \(N\) 变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数 \(N\),表示排列的规模。
第二行是 \(N\) 个不同的数字 \(P_i\),表示这 \(N\) 个数字的某一排列。
输出格式
输出一个整数,表示不同连号区间的数目。
数据范围
\(1≤N≤10000\),
\(1≤P_i≤N\)
输入样例1:
4
3 2 4 1
输出样例1:
7
输入样例2:
5
3 4 2 5 1
输出样例2:
9
样例解释
第一个用例中,有 7 个连号区间分别是:\([1,1],[1,2],[1,3],[1,4],[2,2],[3,3],[4,4]\)
第二个用例中,有 9 个连号区间分别是:\([1,1],[1,2],[1,3],[1,4],[1,5],[2,2],[3,3],[4,4],[5,5]\)
解题思路
注意到这是一个排列,没有重复值,则一段连续区间的长度为【最大值-最小值+1】,据此便可解题~
- 时间复杂度:\(O(n^2)\)
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[10005],res;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int mn,mx;
for(int i=1;i<=n;i++)
{
mn=a[i],mx=a[i];
for(int j=i;j<=n;j++)
{
mn=min(mn,a[j]),mx=max(mx,a[j]);
if(j-i==mx-mn)res++;
}
}
printf("%d",res);
return 0;
}