2016年蓝桥杯C++ 本科B组+高职组题目汇总(填空题+代码填空题)

1.一步之遥

从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。

小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。

矿车上的动力已经不太足,黄色的警示灯在默默闪烁…
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。

请填写为了达成目标,最少需要操作的次数。

注意,需要提交的是一个整数,不要填写任何无关内容(比如:解释说明等)

答案:97

思路:我用的广搜,深搜应该也可以吧,但是个人感觉用广搜写简单省时间一点,因为求的是最优解。

#include<bits/stdc++.h>
using namespace std;
int ans=-1;
void bfs()
{
	queue<pair<int,int> > q;
	q.push({0,0});
	while(!q.empty())
	{
		ans++;
		pair<int,int> t=q.front();
		q.pop(); 
		if(t.second==1)
		{
			break;
		}
		if(t.second<0)
			q.push({1,t.second+97});
		else
			q.push({-1,t.second-127});
	}
}
int main()
{
	int a=97,b=127;
	bfs();
	cout<<ans<<endl;
	return 0;
}



2.随意组合

小明被绑架到X星球的巫师W那里。

其时,W正在玩弄两组数据 (2 3 5 8) 和 (1 4 6 7)
他命令小明从一组数据中分别取数与另一组中的数配对,共配成4对(组中的每个数必被用到)。
小明的配法是:{(8,7),(5,6),(3,4),(2,1)}

巫师凝视片刻,突然说这个配法太棒了!

因为:
每个配对中的数字组成两位数,求平方和,无论正倒,居然相等:
87^2 + 56^2 + 34^2 + 21^2 = 12302
78^2 + 65^2 + 43^2 + 12^2 = 12302

小明想了想说:“这有什么奇怪呢,我们地球人都知道,随便配配也可以啊!”
{(8,6),(5,4),(3,1),(2,7)}

86^2 + 54^2 + 31^2 + 27^2 = 12002
68^2 + 45^2 + 13^2 + 72^2 = 12002

巫师顿时凌乱了。。。。。

请你计算一下,包括上边给出的两种配法,巫师的两组数据一共有多少种配对方案具有该特征。
配对方案计数时,不考虑配对的出现次序。
就是说:
{(8,7),(5,6),(3,4),(2,1)}

{(5,6),(8,7),(3,4),(2,1)}
是同一种方案。

注意:需要提交的是一个整数,不要填写任何多余内容(比如,解释说明文字等)

答案:24

思路:刚开始的时候看了半天,不知道怎么去重,后来输出看了下,发现,它不考虑配对的顺序,那么一组数固定,全排列另一组就可以了。

#include<bits/stdc++.h>
using namespace std;
int a[10]={2,3,5,8};
int b[10]={1,4,6,7};
map<int,int> mp;
int check()
{
	int sum1=0,sum2=0;
	for(int i=0;i<4;i++)
	{
		int x=a[i]*10+b[i];
		sum1+=x*x;
		mp[x]++;
	}
	for(int i=0;i<4;i++)
	{
		int x=b[i]*10+a[i];
		sum2+=x*x;
		mp[x]++;
	}
	return sum1==sum2;
}
int main()
{
	int ans=0;
	do
	{
		if(check())
			ans++;
	}while(next_permutation(b,b+4));
	cout<<ans<<endl;
	return 0;
}



3.平方末尾

能够表示为某个整数的平方的数字称为“平方数”
比如,25,64
虽然无法立即说出某个数是平方数,但经常可以断定某个数不是平方数。
因为平方数的末位只可能是:[0, 1, 4, 5, 6, 9] 这6个数字中的某个。
所以,4325435332必然不是平方数。

如果给你一个2位或2位以上的数字,你能根据末位的两位来断定它不是平方数吗?

请计算一下,一个2位以上的平方数的最后两位有多少种可能性?

注意:需要提交的是一个整数,表示2位以上的平方数最后两位的不同情况数。
不要填写任何多余内容(比如,说明解释文字等)

答案:22

暴力就行了,注意去重

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	set<int> st;
	for(int i=4;i<=10000;i++) //边界可以自己定,多试几个边界,看看结果一样不一样
	{
		ll x=(ll)i*i;
		st.insert(x%100);
	}
	set<int>::iterator it;
	for(it=st.begin();it!=st.end();it++)  //最好输出一下看看自己做对没
		cout<<*it<<" ";
	cout<<endl<<st.size()<<endl;
	return 0;
}



4.愤怒小鸟

X星球愤怒的小鸟喜欢撞火车!

一根平直的铁轨上两火车间相距 1000 米
两火车 (不妨称A和B) 以时速 10米/秒 相对行驶。

愤怒的小鸟从A车出发,时速50米/秒,撞向B车,
然后返回去撞A车,再返回去撞B车,如此往复…
两火车在相距1米处停车。

问:这期间愤怒的小鸟撞 B 车多少次?

注意:需要提交的是一个整数(表示撞B车的次数),不要填写任何其它内容。

答案:9

#include<bits/stdc++.h>
using namespace std;
int main()
{
	double a=0,b=1000,t;
	int flag=1,ans=0;
	while(b-a>1)
	{
		t=(b-a)/60.0;   //t表示此时到下次相撞需要的时间。因为方向相反,所以总体速度为60
		a+=10*t;
		b-=10*t;
		if(flag)   //flag为1的话表示此次和B相撞,所以一开始需给flag赋值为1
			ans++;
		flag=!flag;   //下次撞的是另一边
	}
	cout<<ans<<endl;
	return 0;
}



5.反幻方

我国古籍很早就记载着

2 9 4
7 5 3
6 1 8

这是一个三阶幻方。每行每列以及对角线上的数字相加都相等。

下面考虑一个相反的问题。
可不可以用 1~9 的数字填入九宫格。
使得:每行每列每个对角线上的数字和都互不相等呢?

这应该能做到。
比如:
9 1 2
8 4 3
7 5 6

你的任务是搜索所有的三阶反幻方。并统计出一共有多少种。
旋转或镜像算同一种。

比如:
9 1 2
8 4 3
7 5 6

7 8 9
5 4 1
6 3 2

2 1 9
3 4 8
6 5 7

等都算作同一种情况。

请提交三阶反幻方一共多少种。这是一个整数,不要填写任何多余内容。

答案:3120

思路:直接全排列就好了。注意最后结果需要除以8。(四种旋转,每种有两个镜像)
自己当时想的时候少算了两种情况,就想着4种旋转+2种镜像=6了。(难受qaq)

#include<bits/stdc++.h>
using namespace std;
int a[15]={1,2,3,4,5,6,7,8,9};
int vis[50];
int main()
{
	int ans=0,x;
	do
	{
		int flag=0;
		memset(vis,0,sizeof(vis));
		x=a[0]+a[1]+a[2];vis[x]++;
		x=a[4]+a[5]+a[3];vis[x]++;
		x=a[6]+a[7]+a[8];vis[x]++;
		x=a[0]+a[3]+a[6];vis[x]++;
		x=a[1]+a[4]+a[7];vis[x]++;
		x=a[2]+a[5]+a[8];vis[x]++;
		x=a[0]+a[4]+a[8];vis[x]++;
		x=a[2]+a[4]+a[6];vis[x]++;
		for(int i=1;i<=27;i++)
			if(vis[i]>1)
			{
				flag=1;break;
			}
		if(!flag)
			ans++;
	}while(next_permutation(a,a+9));
	cout<<ans/8<<endl;
	return 0;
}



6.凑平方数

把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721

再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…

注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。

如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?

注意:需要提交的是一个整数,不要填写多余内容。

答案:300

思路:全排列+搜索

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[15]={0,1,2,3,4,5,6,7,8,9};
int cnt,ans;
ll res[15];
ll tem[15];
map<string,int> mp;
bool judge(ll x)  //判断x是否为平方数
{
	return x==(ll)sqrt(x)*(ll)sqrt(x); //注意必须要强制类型转换
}
void dfs(int x,int num)
{
	if(x>10)
		return;
	if(x==10)
	{
		string s,ss;
		for(int i=0;i<num;i++)
			tem[i]=res[i];
		sort(tem,tem+num);   //用tem记录原来的数,排序是为了去重方便一些,因为题目说不计较顺序
		for(int i=0;i<num;i++)
		{
			ss.clear();
			ll xx=tem[i];
			while(xx)
			{
				ss+=xx%10+'0';
				xx/=10;
			}
			reverse(ss.begin(),ss.end());  //转置的原因是上面拼接的时候是倒着拼接的
			s+=ss;        //将找出来的完全平方数转化为字符串,拼接在一起
			s+=',';       //注意要使用字符将数字们分开
		}
		if(!mp[s])   //若已经算过,就不再算了
		{
			mp[s]=1;
			ans++;	
		}
		return;
	}
	if(a[x]==0)  //一个数的开头不能为0,所以如果在开头,它只能单另作为一个数
	{
		res[num]=0;
		dfs(x+1,num+1);
		return;
	}
	ll t=0;
	for(int i=x;i<=10;i++) //枚举与它身后的数字们结合是否能产生平方数
	{
		t=t*10+a[i];
		if(judge(t))
		{
			res[num]=t;
			dfs(i+1,num+1);
		}
	}
}
int main()
{
	do
	{
		dfs(0,0);
	}while(next_permutation(a,a+10));
	cout<<ans<<endl;
	return 0;
}



7.七星填数

如下图所示。

在七角星的14个节点上填入1~14 的数字,不重复,不遗漏。
要求每条直线上的四个数字之和必须相等。

图中已经给出了3个数字。
请计算其它位置要填充的数字,答案唯一。

填好后,请提交绿色节点的4个数字(从左到右,用空格分开)

比如:12 5 4 8
当然,这不是正确的答案。

注意:只提交4个用空格分开的数字,不要填写任何多余的内容。
在这里插入图片描述

答案:10 3 9 8

全排列

#include<iostream>
#include<algorithm>
using namespace std;
int a[20]={1,2,3,4,5,7,8,9,10,12,13};
int main()
{
	do
	{
		int x1=a[0]+a[1]+a[2]+a[3];
		int x2=a[0]+a[4]+a[6]+a[9];
		int x3=6+a[1]+a[4]+14;
		int x4=6+a[2]+a[5]+11;
		int x5=a[3]+a[5]+a[7]+a[10];
		int x6=14+a[6]+a[8]+a[10];
		int x7=a[9]+a[8]+a[7]+11;
		if(x1==x2 && x1==x3 && x1==x4 && x1==x5 && x1==x6 && x1==x7)
		{
			for(int i=0;i<11;i++)
				cout<<a[i]<<" ";
			cout<<endl;
		}
	}while(next_permutation(a,a+10));
	return 0;
}



8.阶乘位数

9的阶乘等于:362880
它的二进制表示为:1011000100110000000
这个数字共有19位。

请你计算,9999 的阶乘的二进制表示一共有多少位?

注意:需要提交的是一个整数,不要填写任何无关内容(比如说明解释等)

答案:118445

思路:实际上是求log(9999!) = log(1 * 2 * 3 * 4… * 9999) = log(1)+log(2)+log(3)+…log(9999)
注意:以上求对数都是以2为底

#include<bits/stdc++.h>
using namespace std;
int main()
{
	double ans=0;
	for(int i=1;i<=9999;i++)
	{
		ans+=log(i*1.0)/log(2);  //除以log(2)可以换底
	}
	cout<<ans<<endl; //注意最后要四舍五入
	return 0;
}



9.拼棋盘

有 8x8 和 6x6 的棋盘两块(棋盘厚度相同,单面有棋盘,背面无图案)。参见【图1.png】
组成棋盘的小格子是同样大小的正方形,黑白间错排列。

现在需要一个10x10的大棋盘,希望能通过锯开这两个棋盘,重新组合出大棋盘。

要求:
1。 拼好的大棋盘仍然保持黑白格间错的特性。
2。 两个已有的棋盘都只允许锯一锯(即锯开为两块),必须沿着小格的边沿,可以折线锯开。
3。 要尽量保证8x8棋盘的完整,也就是说,从它上边锯下的那块的面积要尽可能小。

要求提交的数据是:4块锯好的部分的面积。按从小到大排列,用空格分开。
(约定每个小格的面积为1)

比如:10 10 26 54
当然,这个不是正确答案。

请严格按要求格式提交数据,不要填写任何多余的内容(比如,说明解释等)

额。。表示不会做…




10.打靶

小明参加X星球的打靶比赛。
比赛使用电子感应计分系统。其中有一局,小明得了96分。

这局小明共打了6发子弹,没有脱靶。
但望远镜看过去,只有3个弹孔。
显然,有些子弹准确地穿过了前边的弹孔。

不同环数得分是这样设置的:
1,2,3,5,10,20,25,50

那么小明的6发子弹得分都是多少呢?有哪些可能情况呢?

下面的程序解决了这个问题。
仔细阅读分析代码,填写划线部分缺失的内容。

#include <stdio.h>
#define N 8

void f(int ta[], int da[], int k, int ho, int bu, int sc)
{
int i,j;
if(ho<0 || bu<0 || sc<0) return;
if(k==N){
if(ho>0 || bu>0 || sc>0) return;
for(i=0; i<N; i++){
for(j=0; j<da[i]; j++)
printf("%d “, ta[i]);
}
printf(”\n");
return;
}

for(i=0; i<=bu; i++){
da[k] = i;
f(ta, da, k+1, _____________ , bu-i, sc-ta[k]*i); //填空位置
}

da[k] = 0;
}

int main()
{
int ta[] = {1,2,3,5,10,20,25,50};
int da[N];
f(ta, da, 0, 3, 6, 96);
return 0;
}

答案:i>0?ho-1:ho

枚举的是有几发一样的子弹从一个孔里面穿过去的,如果弹孔已经枚举完了,自然就不能枚举了,否则的话枚举下一个(ho-1)




11.打印数字

小明写了一个有趣的程序,给定一串数字。
它可以输出这串数字拼出放大的自己的样子。

比如“2016”会输出为:
22222 00000 1 6666
2 2 0 0 1 1 6
2 0 0 1 666666
2 0 0 1 6 6
2 0 0 1 6 6
2 2 0 0 1 6 6
2222222 00000 1111 66666

请仔细分析代码,填写划线部分缺少的内容。

#include <stdio.h>
#include <string.h>
#define ZIW 8
#define ZIH 7
void f(int n)
{
char cc[100];
int i,j;
char di[][ZIH][ZIW] =
{{" 00000 ",
“0 0”,
“0 0”,
“0 0”,
“0 0”,
“0 0”,
" 00000 “},
{” 1 ",
" 1 1 ",
" 1 ",
" 1 ",
" 1 “,
" 1 “,
" 1111”},
{” 22222 “,
“2 2”,
" 2”,
" 2 “,
" 2 “,
" 2 2”,
“2222222”},
{” 33333 “,
“3 3”,
" 3”,
" 3333 “,
" 3”,
“3 3”,
" 33333 “},
{” 44 ",
" 4 4 ",
" 4 4 ",
"4 4 ",
"4 4 ",
“4444444”,
" 4 “},
{” 55555 ",
" 5 ",
“555555 “,
" 5”,
" 5”,
“5 5”,
" 55555 “},
{” 6666 ",
"6 ",
"666666 ",
“6 6”,
“6 6”,
“6 6”,
" 66666 "},
{“7777777”,
"7 7 ",
" 7 ",
" 7 ",
" 7 ",
" 7 ",
" 7 “},
{” 88888 ",
“8 8”,
“8 8”,
" 88888 “,
“8 8”,
“8 8”,
" 88888 “},
{” 99999 “,
“9 9”,
“9 9”,
" 999999”,
" 9”,
“9 9”,
" 99999 "}};

sprintf(cc, “%d”, n);

for(i=0; i<ZIH; i++){
for(j=0; j<strlen(cc); j++){
printf("%s “, _______________________ ); //填空位置
}
printf(”\n");
}
}

int main()
{
f(2016);
return 0;
}

注意:只提交划线部分缺少的代码,不要添加任何题面已有代码或符号。
也不要提交任何说明解释文字等。

答案:di[cc[j]-‘0’][i]




12.棋子换位

有n个棋子A,n个棋子B,在棋盘上排成一行。
它们中间隔着一个空位,用“.”表示,比如:

AAA.BBB

现在需要所有的A棋子和B棋子交换位置。
移动棋子的规则是:

  1. A棋子只能往右边移动,B棋子只能往左边移动。
  2. 每个棋子可以移动到相邻的空位。
  3. 每个棋子可以跳过相异的一个棋子落入空位(A跳过B或者B跳过A)。

AAA.BBB 可以走法:
移动A = => AA.ABBB
移动B = => AAAB.BB

跳走的例子:
AA.ABBB = => AABA.BB

以下的程序完成了AB换位的功能,请仔细阅读分析源码,填写划线部分缺失的内容。

#include <stdio.h>
#include <string.h>

void move(char* data, int from, int to)
{
data[to] = data[from];
data[from] = ‘.’;
}

int valid(char* data, int k)
{
if(k<0 || k>=strlen(data)) return 0;
return 1;
}

void f(char* data)
{
int i;
int tag;
int dd = 0; // 移动方向

while(1){
tag = 0;
for(i=0; i<strlen(data); i++){
if(data[i]= =’.’) continue;
if(data[i]= =‘A’) dd = 1;
if(data[i]= =‘B’) dd = -1;
if(valid(data, i+dd) && valid(data,i+dd+dd)
&& data[i+dd]!=data[i] && data[i+dd+dd]==’.’){
//如果能跳…
move(data, i, i+dd+dd);
printf("%s\n", data);
tag = 1;
break;
}
}

if(tag) continue;

for(i=0; i<strlen(data); i++){
if(data[i]= =’.’) continue;
if(data[i]= =‘A’) dd = 1;
if(data[i]= =‘B’) dd = -1;

if(valid(data, i+dd) && data[i+dd]==’.’){
// 如果能移动…
if( ______________________ ) continue; //填空位置
move(data, i, i+dd);
printf("%s\n", data);
tag = 1;
break;
}
}

if(tag==0) break;
}
}

int main()
{
char data[] = “AAA.BBB”;
f(data);
return 0;
}

注意:只提交划线部分缺少的代码,不要复制已有代码或填写任何多余内容。




猜你喜欢

转载自blog.csdn.net/weixin_43693379/article/details/89644731