蓝桥杯题集

题目链接

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\) 的格子中填写了一些整数。

image

我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是 60。

本题的要求就是请你编程判定:对给定的 \(m×n\) 的格子中的整数,是否可以分割为两个连通的部分,使得这两个区域的数字和相等。

如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。

如果无法分割,则输出 0。

image

输入格式

第一行包含两个整数 \(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;
}
posted @ 2021-10-14 18:50  zyy2001  阅读(82)  评论(0编辑  收藏  举报