【2019年第十届蓝桥杯】 C++ 省赛B组 (题解 + 刷题链接)

刷题网站:

刷题网站 < — 这里可以刷题


第一题 组队

题目链接

题目描述
作为篮球队教练,你需要从以下名单中选出1 号位至5 号位各一名球员,组成球队的首发阵容。
每位球员担任1号位至5号位时的评分如下表所示。请你计算首发阵容1号位至5号位的评分之和最大可能是多少?
在这里插入图片描述

第一题答案:490 (比如1 10 17 11 15)


第二题 年号字串:

题目链接

题目描述
小明用字母A 对应数字1,B 对应2,以此类推,用Z 对应26。对于27以上的数字
小明用两位或更长位的字符串来对应,例如AA 对应27,AB 对应28,AZ 对应52,LQ 对应329。
请问2019 对应的字符串是什么?

可以手算,也可以代码

代码:

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
    string ans;
    char c[27];  //存 A-Z 字符数组
    int a=2019;
    for(int i=1;i<27;i++) c[i]='A'+i-1;
	while(a)
	{
		ans+=c[a%26];
		a/=26;
	}
    for(int i=ans.size()-1;i>=0;i--) cout<<ans[i]; //逆序输出
    return 0;
}

第二题答案 : BYQ


第三题 数列求值:

题目链接

题目描述
给定数列1, 1, 1, 3, 5, 9, 17, …,从第4 项开始,每项都是前3 项的和。求
第20190324 项的最后4 位数字。

代码:

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=20190324;
const int mod=10000;
ll a=1,b=1,c=1,cnt=3;
int main()
{
   	while(1)
   	{
   		ll sum=(a+b+c)%mod; //要先记录下,否则a,b原本的值会变
   		a=b;
   		b=c;
   		c=sum;
   	  	if(++cnt==maxn) break; //第maxn项,结束循环
   	}
   	cout<<c;
    return 0;
}

第三题答案 : 4659


第四题 数的分解:

题目链接

题目描述
把2019分解成3个各不相同正整数之和,并且要求每个正整数都不包含数字2和4,一共有多少种不同的分解方法?
注意交换3个整数的顺序被视为同一种方法,例如1000+1001+18 和1001+1000+18 被视为同一种。

代码:

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
bool in(int x) //判断是否包含2 4
{
	while(x)
	{
		if(x%10==2 || x%10==4) return 0;
		x/=10;
	}
	return 1;
}

int main()
{
	int ans=0;
   	for(int i=1;i<=2019;i++)  // 要为正整数,所以从1开始
   	  for(int j=i+1;j<=2019;j++)
   	    for(int k=j+1;k<=2019;k++)
   	      if(i+j+k==2019 && i!=j && i!=k && j!=k && in(i) && in(j) && in(k)) ans++;
   	cout<<ans;
    return 0;
}

第四题答案 : 40785


第五题 迷宫:

题目链接

下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可
以通行的地方。
010000
000100
001001
110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这
个它的上、下、左、右四个方向之一。
对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫,
一共10 步。其中D、U、L、R 分别表示向下、向上、向左、向右走。
对于下面这个更复杂的迷宫(30 行50 列),请找出一种通过迷宫的方式,
其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。
请注意在字典序中D<L<R<U。

迷宫图形.TXT

代码 (bfs):

#include <iostream>
#include <algorithm>
#include <queue> 
using namespace std;
typedef long long ll;
int dx[]={1,0,0,-1}; //D L R U 按字典序最小建立方向 
int dy[]={0,-1,1,0};
char dir[]={'D','L','R','U'};
char maze[30][50],lastdir[30][50]; //maze迷宫,lastdir上步到该步的方向
int lastpointx[30][50],lastpointy[30][50]; //上步的x,y
bool inq[30][50]={false}; //是否入过队

struct node{ //坐标
	int x,y;
	node(int a,int b){x=a;y=b;}
};

string s="\
01010101001011001001010110010110100100001000101010\
00001000100000101010010000100000001001100110100101\
01111011010010001000001101001011100011000000010000\
01000000001010100011010000101000001010101011001011\
00011111000000101000010010100010100000101100000000\
11001000110101000010101100011010011010101011110111\
00011011010101001001001010000001000101001110000000\
10100000101000100110101010111110011000010000111010\
00111000001010100001100010000001000101001100001001\
11000110100001110010001001010101010101010001101000\
00010000100100000101001010101110100010101010000101\
11100100101001001000010000010101010100100100010100\
00000010000000101011001111010001100000101010100011\
10101010011100001000011000010110011110110100001000\
10101010100001101010100101000010100000111011101001\
10000000101100010000101100101101001011100000000100\
10101001000000010100100001000100000100011110101001\
00101001010101101001010100011010101101110000110101\
11001010000100001100000010100101000001000111000010\
00001000110000110101101000000100101001001000011101\
10100101000101000000001110110010110101101010100001\
00101000010000110101010000100010001001000100010101\
10100001000110010001000010101001010101011111010010\
00000100101000000110010100101001000001000000000010\
11010000001001110111001001000011101001011011101000\
00000110100010001000100000001000011101000000110011\
10101000101000100010001111100010101001010000001000\
10000010100101001010110000000100101010001011101000\
00111100001000010000000110111000000001000000001011\
10000001100111010111010001000110111010101101111000";

int bfs(int x,int y)
{
	queue<node> q;
	q.push(node(0,0));
	lastdir[0][0]='?'; //起点标记?
	inq[0][0]=1;  
	
	while(!q.empty())
	{
		x=q.front().x;
		y=q.front().y;
		q.pop();
		for(int i=0;i<4;i++)
		{
			int newx=x+dx[i];
			int newy=y+dy[i];
			if(!inq[newx][newy]&&newx>=0&&newx<30&&newy>=0&&newy<50&&maze[newx][newy]=='0')
			//没入过队,在范围内,maze是路
			{
				inq[newx][newy]=1;
				lastdir[newx][newy]=dir[i]; //记录方向
				lastpointx[newx][newy]=x;  //记录上步的x
				lastpointy[newx][newy]=y;  //记录上步的y
				q.push(node(newx,newy));
			}
		}
	}	
}

int main()
{
	int a=0,b=0;
	for(int i=0;i<s.size();i++) //根据字符串建图 
	{
		maze[a][b++]=s[i];
		if(b==50) a++,b=0; //满50换行 
	} 
	bfs(0,0);
	string ans;
	int nx=29,ny=49;
	while(lastdir[nx][ny]!='?') //直到起点
	{
		ans+=lastdir[nx][ny]; 
		int x=nx,y=ny;  //记录下nx,ny,否则会变
		nx=lastpointx[x][y];
		ny=lastpointy[x][y];
	}
	reverse(ans.begin(),ans.end());  // 倒置
	cout<<ans;
    return 0;
}

第五题答案:DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR


第六题 特别数的和:

题目链接

题目描述
小明对数位中含有2、0、1、9 的数字很感兴趣(不包括前导0)
在1到40中这样的数包括1、2、9、10 至32、39 和40,共28 个,他们的和是574。
请问,在1到n 中,所有这样的数的和是多少?
输入
输入一个正整数n(1<=n<=10000)
输出
输出一行,包含一个整数,表示满足条件的数的和。
样例输入

40

样例输出

574

代码:

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

bool is(int x) //判断是否含有 2 0 1 9 
{
	while(x) 
	{
		int a=x%10;
		if(a==2 || a==0 || a==1 || a==9) return 1;
		x/=10;
	}
	return 0;
}

int main()
{
	ll n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
		if(is(i)) ans+=i; //有 则累加
	cout<<ans;
    return 0;
}


第七题 完全二叉树的权值:

(完全二叉树不一定是满二叉树!!!) //一开始想错了
(完全二叉树不一定是满二叉树!!!)
(完全二叉树不一定是满二叉树!!!)
(完全二叉树不一定是满二叉树!!!)
(完全二叉树不一定是满二叉树!!!)
(完全二叉树不一定是满二叉树!!!)

题目链接

题目描述
给定一棵包含N 个节点的完全二叉树,树上每个节点都有一个权值,按从
上到下、从左到右的顺序依次是A1, A2, AN,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点
权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是1。
输入
第一行包含一个整数N。
第二行包含N 个整数A1, A2, AN
对于所有评测用例,1<=N<=100000, -100000<=Ai<=100000。
输出
输出一个整数代表答案。
样例输入

7
1 6 5 4 3 2 1

样例输出

2

代码:

(只有最后一层可能没满,上面层都应该是满的)

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=100010;
int a[maxn];
int main()
{
	int n,deep=1,cnt=2,now=1,nowdeep=1; 
	//deep深度,cnt该层最大节点数,now现在所处Ai位置,nowdeep当前深度
	cin>>n;
	for(int i=0;i<n;i++)
	   cin>>a[i];
	   
	int val=a[0];   //val初始值为根权
	while(now<n)
	{
		++nowdeep; //当前深度+1
		int sum=0,nown=now+cnt;  //sum记录该层总权,nown该层最后节点位置
		if(now+cnt>n) nown=n;  //最后一层没满的情况
		for(int i=now;i<nown;i++)
		   sum+=a[i]; //该层权和
		if(sum>val) val=sum,deep=nowdeep; //只有大于val才更新
		now+=cnt; //所处位置+该层节点数量
		cnt*=2;  //下一层最大节点数是当前的两倍
	}
	cout<<deep;
    return 0;
}


第八题 等差数列:

题目链接

题目描述
数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中N 个整数。
现在给出这N 个整数,小明想知道包含这N 个整数的最短的等差数列有几项?
输入
输入的第一行包含一个整数N。
第二行包含N 个整数A1.A2,…, AN。(注意A1<=AN 并不一定是按等差数列中的顺序给出)
2<=N<=100000,0<=Ai<=10^9
输出
输出一个整数表示答案。
样例输入

5
2 6 4 10 20

样例输出

10

提示
包含2、6、4、10、20 的最短的等差数列是2、4、6、8、10、12、14、16、18、20。

代码:

要注意考虑公差为0的情况(常数数列)

先排序,求所有相邻差的最大公约数

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=100010;
int a[maxn],n,cnt=0,flag=0;

int gcd(int x,int y){ //最大公约数
	return y==0?x:gcd(y,x%y);
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	   cin>>a[i];
	sort(a,a+n);  //排序
	int cha=a[1]-a[0];  //第一个差
	if(!cha) flag=1;  //常数数列
	for(int i=2;i<n;i++)
	{
		if(flag) break; //若为常数数列,就break
		cha=gcd(cha,a[i]-a[i-1]); //取最大公约数
	}
	if(!flag) cout<<(a[n-1]-a[0])/cha+1; //非常数数列
	else  cout<<n; //常数数列
    return 0;
}


第九题 后缀表达式:

题目链接

题目描述
给定N 个加号、M 个减号以及N + M + 1 个整数A1,A2,…,AN+M+1
小明想知道在所有由这N 个加号、M 个减号以及N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则“2 3 + 1 -” 这个后缀表达式结果是4,是最大的。
输入
第一行包含两个整数N 和M。
第二行包含N + M + 1 个整数A1,A2,…,AN+M+1
0<=N,M<=100000,-109<=Ai<=109
输出
输出一个整数,代表答案。
样例输入
1 1
1 2 3
样例输出
4

代码 (没AC : 30分)有想法再做 :

没考虑到括号(对后缀表达式不了解)),只考虑了符号放的位置。

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=100010;
ll n,m,x,z[maxn],f[maxn],cnt1=0,cnt2=0,sum=0,nowz=0,nowf=0;

int cmp(int a,int b){
	return a>b;
}

int main()
{
	cin>>n>>m;
	for(int i=0;i<n+m+1;i++) 
	{
		cin>>x;
		if(x>=0) z[cnt1++]=x;
		else f[cnt2++]=x;
	}
	sort(z,z+cnt1,cmp); //从大到小排序 
	sort(f,f+cnt2,cmp); 
	
	
	if(n<cnt1)	for(;nowz<=n;nowz++) sum+=z[nowz];
	else
	{
		for(;nowz<cnt1;nowz++) sum+=z[nowz];
		for(;nowf<=n-cnt1;nowf++) sum+=f[nowf];
	}
	
	if(m<cnt2-nowf) for(;nowf<=m;nowf++) sum-=f[nowf];
	else 
	{
		for(;nowz<cnt1;nowz++) sum-=z[nowz];
		for(;nowf<cnt2;nowf++) sum-=f[nowf];
	}
	
	
	cout<<sum;
    return 0;
}


第十题 灵能传输

题目描述
在这里插入图片描述
输入
在这里插入图片描述
在这里插入图片描述
输出
在这里插入图片描述
样例输入

3
3
5 -2 3
4
0 0 0 0
3
1 2 3

样例输出

3
0
3

提示

对于第一组询问:
对2 号高阶圣堂武士进行传输操作后a1 = 3,a2 = 2,a3 = 1。答案为3。
对于第二组询问:
这一组高阶圣堂武士拥有的灵能都正好可以让他们达到最佳战斗状态。

代码 (就4分不好意思放上来):

以后再说吧。。。(一般这句话代表这题没有以后了。。)
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值