第十届蓝桥杯C/C++ 大学B组省赛题目及答案解析

试题A:组队

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
team.txt文件内容如下:

97 90 0 0 0
92 85 96 0 0
0 0 0 0 93
0 0 0 80 86
89 83 97 0 0
82 86 0 0 0
0 0 0 87 90
0 97 96 0 0
0 0 89 0 0
95 99 0 0 0
0 0 96 97 0
0 0 0 93 98
94 91  0 0 0
0 83 87 0 0
0 0 98 97 98
0 0 0 93 86
98 83 99 98 81
93 87 92 96 98
0 0 0 89 92
0 99 96 95 81

【答案】 :490

【代码解析】

#include<iostream>
using namespace std;
int score[60][60],result;
bool vis[60];
void dfs(int num,int sum)//num:已经选了几个数,几号队员(本题正好相等),sum:当前分数总和 
{
	if(num>5)
	{
		result=max(result,sum);
		return;
	}
	for(int i=1;i<=20;i++)
	{
		if(!vis[i])
		{
			vis[i]=true;
			dfs(num+1,sum+score[i][num+1]);
			vis[i]=false;
		}
	}
}
int main()
{
	for(int i=1;i<=20;i++)
	    for(int j=1;j<=5;j++)
	    {
	    	cin >> score[i][j];
		}
	//读入数据 
	dfs(0,0);
	cout << result << endl;
	return 0;
}

试题B:年号字串

在这里插入图片描述
【答案】 :BYQ

【代码解析】
看起来是一个进制问题,也确实是一个26进制,但一定要认识到它的特殊性。
具体代码如下:

#include<iostream>
using namespace std;
int c[100];
int main()
{
    int a=2019;
    int i=0;
    int temp=a;   
    while(a)
    {
        temp=a%26;
		c[i++]=temp;                
		a/=26;  
    }
    for(int j=i-1;j>=0;j--)
    {
			printf("%c",'A'+c[j]-1);      
    } 
    return 0;
} 

特殊性在于:虽然不影响答案,但在“进位”的时候会出现问题,是因为题目规定的初始状态A是1而不是0,所以26对应的字符串已经进位但实际上不应该进,导致结果是A@而不是Z。
如果觉得不舒服的同学可以选择采取从后往前推的办法,代码如下:

#include<iostream>
using namespace std;
int main()
{
	for (int i = 1; i <= 26; i++){
            for (int j = 1; j <= 26; j++){
                for (int k = 1; k <= 26; k++){
                    if (i * 26 * 26 + j * 26 + k == 2019)
                    {
                    	cout <<(char)('A' + i-1);
                        cout <<(char)('A' + j-1);
                        cout <<(char)('A' + k-1);
					}                      
                }
            }
        }       
	return 0;
}

两种方式均可以,但此题的关键是要熟悉进制转换。

试题C:数列求值

在这里插入图片描述
【答案】:4659

【代码解析】

#include<iostream>
using namespace std;
long long dp[100000000];
int main()
{
	dp[1]=dp[2]=dp[3]=1;
	for(int i=4;i<=20190324;i++)
	{
		dp[i]=(dp[i-1]+dp[i-2]+dp[i-3])%10000;
	}
	cout << dp[20190324] << endl;
	return 0;
}

但注意,千万不要把写递归函数,本题数据量太大,反复的递归调用会导致栈溢出,无法运行出结果,感兴趣的同学可以尝试:

#include<iostream>
using namespace std;
int fun(int m)
{    
    if(m==1||m==2||m==3) return 1;
    else{
    	return (fun(m-1)+fun(m-2)+fun(m-3))%10000;
	}
}
int main()
{
	cout << fun(20190324) << endl;
	return 0;
}

试题D:数的分解

在这里插入图片描述
【答案】:40785
【代码解析】
可DFS,可直接循环,本题的思路还是比较明确的。
DFS版本(时间有些长,大约3.5s):

#include<iostream>
using namespace std;
const int N=3000;
int k;
bool vis[N];
inline bool judge(int x)
{
	while(x)
	{
		int k=x%10;
		x/=10;
		if(k==2||k==4)
		{
			return false;
		}
	}
	return true;
}
void dfs(int n,int sum,int l)//n:当前选了几个数,sum:当前总和,l:确保从小到大扫描 
{
	if(sum>2019)
	{
		return;
	}
	if(n==3)
	{
		if(sum==2019)
		{
		   k++;
		   return;	
		}
		else{
			return;
		}
	}
	for(int i=l;i<=2019;i++)
	{
		if(!vis[i]&&judge(i))
		{
			vis[i]=true;
			dfs(n+1,sum+i,i+1);
			vis[i]=false;
		}
	}
}
int main()
{	
	dfs(0,0,1);
	cout << k << endl;
	return 0;
}

循环版本(秒出):

#include<iostream>
using namespace std;
inline bool judge(int x)
{
	while(x)
	{
		int k=x%10;
		if(k==2||k==4)
		{
			return false;
		}
		x/=10;
	}
	return true;
}
int main()
{	
	int sum=0;
	for(int i=1;i<=2019;i++)
	{
	    if(judge(i))
		for(int j=i+1;j<=2019;j++)
		{
			if(judge(j))
			{
				int k=2019-i-j;
			    if(k>j&&judge(k))
			   {
			     sum++;	
			   }
			}			
		}
	}
	cout << sum << endl;
	return 0;
}

试题E:迷宫

在这里插入图片描述
文本如下:

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

在这里插入图片描述
【答案】:DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUU
UULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR

【代码解析】
按照题目要求,需要找到步数最少的一条路径,首先想到BFS,至于字典序最小,只要在转换方向时按照“DULR”的方向走即可,队列中要有走到该处的X,Y坐标,走到这里的路径字符,步数(可有可无)几个元素,最后输出走到右下角点的路径字符即可。
总体而言思路比较明确,考察BFS模板。在做代码量较大的题的时候,一定要保持细心。
代码如下:

#include<iostream>
#include<queue>
using namespace std;
char map[60][60];
int dir[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
bool vis[60][60];
string m="DLRU";
struct node{
	int x,y;
	string s;
	node(int xx,int yy,string ss)
	{
		x=xx;
		y=yy;
		s=ss;
	}
};
bool in(int x,int y)
{
	return x>=1&&x<=30&&y>=1&&y<=50;
}
string bfs(int x,int y)
{
	queue<node> q;
	q.push(node(x,y,""));
	vis[x][y]=true;
	while(!q.empty())
	{
		node now=q.front();
		q.pop();
		if(now.x==30&&now.y==50)
		{
			return now.s;
		}
		for(int i=0;i<4;i++)
		{
			int tx=now.x+dir[i][0];
			int ty=now.y+dir[i][1];
			if(in(tx,ty)&&map[tx][ty]=='0'&&!vis[tx][ty])
			{
					vis[tx][ty]=true;
					q.push(node(tx,ty,now.s+m[i]));
				}
			}
		}
	}
int main()
{	
	for(int i=1;i<=30;i++)
	{
		for(int j=1;j<=50;j++)
	    {
	 	 cin >> map[i][j];
	    }
	}	  	 
	cout << bfs(1,1) << endl;
	return 0;
}

试题F:特别数的和

在这里插入图片描述
在这里插入图片描述
【代码解析】
作为第一道大题还是很简单滴,数据量也不大,才10000。
代码如下:

#include<iostream>
using namespace std;
int main()
{
	int count;
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		int ans=i;
		int sum=i;
		while(ans)
		{
			int k=ans%10;
			if(k==2||k==0||k==1||k==9)
			{
			   count+=i;
			   break;	
			}
			ans/=10;
		}
	}
	cout << count << endl;
	return 0;
}

试题G:完全二叉树的权值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【代码解析】
思路明确,题不难。
代码如下:

#include<iostream>
using namespace std;
const int N=1e5+5;
int X=-N,Y;
int main()
{
	int leave;
	cin >> leave;
	int number[N];
	for(int i=1;i<=leave;i++)
	{
		cin >> number[i];
	}	
	int sum[N];
	int i=1;
	int deep=1;
	int m=1;
	while(m!=leave+i)
	{
		for(int j=i;j<=m;j++)
		{
			sum[deep]+=number[j];
		}
		deep++;		
		i*=2;
		m+=i;
	}	
	for(int n=1;n<deep;n++)
	{
		if(sum[n]>X)
		{
			X=sum[n];
			Y=n;
		}
	}
	cout << Y << endl;
	return 0;
}

试题H:等差数列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【代码解析】
正确做法应该是排序后,计算相邻两个数之间的最大公因数,然后后面就迎刃而解了,即使是想法错误,也差不离,骗一些分还是可以的。
代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,more;
int series[N];
int gcd(int x,int y)
{
	return y==0?x:gcd(y,x%y);
}
int main()
{
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin >> series[i];
	}
	sort(series+1,series+n+1);
	int min_gap=series[n]-series[1];
	if(min_gap==0)
	{
		cout << n << endl;
	}
	else{
		for(int i=2;i<=n;i++)
		{
			min_gap=min(min_gap,gcd(series[i],series[i-1]));
		}		
	}
	cout << (series[n]-series[1])/min_gap+1 << endl;
	return 0;
}

试题I:后缀表达式

在这里插入图片描述
在这里插入图片描述
【代码解析】
这个博主写的特别好,把我想说的全说了,大家可以看看他写的java版本以及分析,这里我给出C++的代码:
点击此处到达java版本以及详细分析

#include<iostream>
using namespace std;
const int X=1e5+5;
int N,M;
int number[X];
int min_,max_;
long sum=0;
int main()
{
	cin >> N >> M;
	for(int i=0;i<N+M+1;i++)
	{
		cin >> number[i];
		if(number[min_]>number[i])
			{
				min_=i;
			}
		if(number[max_]<number[i])
			{
				max_=i;
			}
	}
	if(M==0)
		{
			for(int i=0;i<N+M+1;i++)
			{
				sum +=number[i];
			}
		    cout << sum << endl;
		}
		else
		{
			for(int i=0;i<N+M+1;i++)
			{
				sum +=abs(number[i]);
			}			
			sum=(sum-2*abs(number[min_]));
			cout << sum << endl;			
		}
	return 0;
}


试题J:灵能传输

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面是题中所给的另一组样例:
输入:

3
5
6 -4 2 -7 3
10
-99 -53 43 80 -83 72 99 78 -63 -9
100
373837389 225627048 -847064399 487662607 579717002 903937892 -89313283 134706789 259978604 399131737 298183518 62083619 -444218530 403702220 358088455 -973959249 -637339048 -736509394 -552801709 -98262597 -532577703 -393599463 762744971 -683270041 716127816 -991756495 734780346 27919355 -421469435 258728334 844409214 -270792553 -490888330 133696186 843888283 -35439761 -73481392 -118968548 269164182 978558860 522378250 -979427259 -330256906 235192566 -652699569 -708569352 -778693386 241745676 583226906 121065292 -503683097 599394257 405122877 437067802 238539735 -957745973 -843677563 -690555937 908484805 940157941 524765035 730436972 -17856720 -530595388 -727773574 617781285 491720304 -779040285 -298295760 -699402143 230749576 404009775 126806094 -140842651 198136484 681875881 997449600 898972467 -239590302 -62193410 866009412 -401154712 -276085482 593177187 -236793216 487533624 75511548 -446699920 -869912037 -330666015 268937148 -430325605 -635949275 361887555 -855294881 87004526 782523543 -69083645 -965396597 -880697065 

输出:

5
88
381470940

在这里插入图片描述
本题较大,等日后有机会再给大家做出解答。

可以先看看其他博主:
点击此处进入:博客1
点击此处进入:博客2
点击此处进入:博客3

以上仅供参考。

最后大家有疑问的话可以评论区留言讨论,有写的不好的地方,不清楚的地方博主还会继续更新,希望大家支持!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值