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

1.哥德巴赫分解

哥德巴赫猜想认为:不小于4的偶数都可以表示为两个素数的和。

你不需要去证明这个定理,但可以通过计算机对有限数量的偶数进行分解,验证是否可行。

实际上,一般一个偶数会有多种不同的分解方案,我们关心包含较小素数的那个方案。
对于给定数值范围,我们想知道这些包含较小素数方案中最大的素数是多少。

比如,100以内,这个数是19,它由98的分解贡献。

你需要求的是10000以内,这个数是多少?

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

答案:173

include<bits/stdc++.h>
using namespace std;
bool isprime(int x)
{
	for(int i=2;i<=sqrt(x);i++)
		if(x%i==0)
			return false;
	return true;
}
int main()
{
	int ans=1,n;
	cin>>n;
	for(int i=n;i>=4;i-=2)
	{
		for(int j=2;j<=i;j++)
		{
			if(isprime(j) && isprime(i-j))
			{
				ans=max(ans,j);break;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}


2.数字划分

w星球的长老交给小明一个任务:
1,2,3…16 这16个数字分为两组。
要求:
这两组数字的和相同,
并且,两组数字的平方和也相同,
并且,两组数字的立方和也相同。

请你利用计算机的强大搜索能力解决这个问题。
并提交1所在的那个分组的所有数字。

这些数字要从小到大排列,两个数字间用一个空格分开。
即类似:1 4 5 8 … 这样的答案。

注意,只提交这一组数字,不要填写任何多余的内容。


笨笨有话说:
只要一个组的成员确定了,另一个组的成员也就确定了。枚举一个组的成员就可以了。
凭直觉,两个组的成员数目不会差太多吧。
歪歪有话说:
既然求 1 所在的那个组,那只要枚举剩余的成员就可以了。
貌似都是8个成员的可能性很大啊。

答案:1 4 6 7 10 11 13 16

思路:暴力搜索就行,题目最后给的提示很有用

#include<bits/stdc++.h>
using namespace std;
int vis[20];
int a[20];
int sum1,sum2,sum3,flag;
void dfs(int num,int sum,int sqrt,int lifang)
{

	if(sum>sum1/2 || sqrt>sum2/2 || lifang>sum3/2 || flag)
		return;	
	//cout<<num<<" "<<sum<<" "<<sqrt<<" "<<lifang<<endl;
	//cout<<"in"<<endl;
	if(sum==sum1/2 && sqrt==sum2/2 && lifang==sum3/2)
	{
		flag=1;
		for(int i=0;i<num;i++)
			cout<<a[i]<<" ";
		return;
	}
	for(int i=1;i<=16;i++)
	{
		if(!vis[i])
		{
			a[num]=i;
			vis[i]=1;
			dfs(num+1,sum+i,sqrt+i*i,lifang+i*i*i);
			vis[i]=0;
		}
	}
}
int main()
{
	vis[1]=1;
	a[0]=1;
	for(int i=1;i<=16;i++)
	{
		sum1+=i;
		sum2+=i*i;
		sum3+=i*i*i;
	}
	cout<<sum1<<" "<<sum2<<" "<<sum3<<endl;
	dfs(1,1,1,1);
	return 0;
}


3.数位和

数学家高斯很小的时候就天分过人。一次老师指定的算数题目是:1+2+…+100。
高斯立即做出答案:5050!

这次你的任务是类似的。但并非是把一个个的数字加起来,而是对该数字的每一个数位作累加。
这样从1加到100的“和”是:901

从10加到15是:21,也就是:1+0+1+1+1+2+1+3+1+4+1+5,这个口算都可以出结果的。

按这样的“加法”,从1加到1000是多少呢? 请通过浏览器提交该结果。

当然,我们并不期望你能像高斯一样,发现数字背后深奥的秘密,只要请计算机帮忙,一切都easy!

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

答案:13501

#include<bits/stdc++.h>
using namespace std;
int f(int x)
{
	int sum=0;
	while(x)
	{
		sum+=x%10;
		x/=10;
	}
	return sum;
}
int main()
{
	int n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		ans+=f(i);
	}
	cout<<ans<<endl;
	return 0;
}


4.36进制

对于16进制,我们使用字母A-F来表示10及以上的数字。
如法炮制,一直用到字母Z,就可以表示36进制。

36进制中,A表示10,Z表示35,AA表示370

你能算出 MANY 表示的数字用10进制表示是多少吗?

请提交一个整数,不要填写任何多余的内容(比如,说明文字)

答案:1040254

思路:像十进制一样做就好了

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	cin>>s;
	int len=s.size();
	int ans=0;
	for(int i=0;i<len;i++)
	{
		int x=s[i]-'A'+10;
		cout<<x<<endl;
		ans*=36;
		ans+=x;
	}
	cout<<ans<<endl;
	return 0;
}


5.平方十位数

由0~9这10个数字不重复、不遗漏,可以组成很多10位数字。
这其中也有很多恰好是平方数(是某个数的平方)。

比如:1026753849,就是其中最小的一个平方数。

请你找出其中最大的一个平方数是多少?

注意:你需要提交的是一个10位数字,不要填写任何多余内容。

思路:全排列+暴力就好

#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 main()
{
	ll ans=0;
	do
	{
		if(!a[0])
			continue;
		ll x=a[0];
		for(int i=1;i<=9;i++)
			x=x*10+a[i];
		if((ll)sqrt(x)*sqrt(x)==x)
		{
			ans=max(ans,x);
			//cout<<x<<endl;
		}
	}while(next_permutation(a,a+10));
	cout<<ans<<endl;
	return 0;
}


6.生命游戏

康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
这个游戏在一个无限大的2D网格上进行。

初始时,每个小方格中居住着一个活着或死了的细胞。
下一时刻每个细胞的状态都由它周围八个格子的细胞状态决定。

具体来说:

  1. 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
  2. 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
  3. 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
  4. 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)

当前代所有细胞同时被以上规则处理后, 可以得到下一代细胞图。按规则继续处理这一代的细胞图,可以得到再下一代的细胞图,周而复始。

例如假设初始是:(X代表活细胞,.代表死细胞)


.XXX.

下一代会变为:

…X…
…X…
…X…

康威生命游戏中会出现一些有趣的模式。例如稳定不变的模式:


.XX.
.XX.

还有会循环的模式:

… … …
.XX… .XX… .XX…
.XX… .X… .XX…
…XX. -> …X. -> …XX.
…XX. …XX. …XX.
… … …

本题中我们要讨论的是一个非常特殊的模式,被称作"Gosper glider gun":


…X…
…X.X…
…XX…XX…XX.
…X…X…XX…XX.
.XX…X…X…XX…
.XX…X…X.XX…X.X…
…X…X…X…
…X…X…
…XX…

答案:166666713

这个博客讲的挺详细的,自己的代码还是有点问题。。https://www.cnblogs.com/chiweiming/p/10693184.html



7.图书排列

将编号为1~10的10本书排放在书架上,要求编号相邻的书不能放在相邻的位置。
请计算一共有多少种不同的排列方案。

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

答案:479306

思路:全排列+暴力

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


8.磁砖样式

小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。

小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何22的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 2
3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】

但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

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

在这里插入图片描述

答案:101466

思路:dfs,记得去重

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int a[105][105];
map<string,int> mp;
int check()   //检查是否存在相同颜色的边长为4的小正方形
{
	for(int i=0;i<n-1;i++)
		for(int j=0;j<m-1;j++)
		{
			if(a[i][j]==a[i][j+1] && a[i][j]==a[i+1][j] && a[i][j]==a[i+1][j+1] )
				return 0;
		}
	return 1;
}
int judge()  //用map去重
{
	string s;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
		{
			s+=a[i][j]+'0';
		}
	if(mp[s])
		return 0;
	mp[s]=1;
	return 1;
}
void dfs(int num)
{
	if(num>=n*m)
	{
		if(check() && judge())
			ans++;
		return;
	}
	int x,y,flag=1;
	for(int i=0;i<n && flag;i++)
		for(int j=0 ;j<m && flag;j++)
			if(!a[i][j])
			{
				x=i;y=j;flag=0;
			}
	if(y+1<m && !a[x][y+1])
	{
		a[x][y]=a[x][y+1]=1;
		dfs(num+2);
		a[x][y]=a[x][y+1]=2;
		dfs(num+2);
		a[x][y]=a[x][y+1]=0;
	}
	if(x+1<n && !a[x+1][y])
	{
		a[x][y]=a[x+1][y]=1;
		dfs(num+2);
		a[x][y]=a[x+1][y]=2;
		dfs(num+2);
		a[x][y]=a[x+1][y]=0;
	}
}
int main()
{
	cin>>n>>m;
	dfs(0);
	cout<<ans<<endl;
	return 0;
}


9.表达式计算

虽然我们学了许久的程序设计,但对于简单的四则混合运算式,如果让我们完全白手起家地编程来解析,还是有点棘手。

这里,我们简化一下问题,假设只有加法和乘法,并且没有括号来改变优先级。
再假设参加运算的都是正整数。

在这么多的限制条件下,表达式的解析似乎简单了许多。
下面的代码解决了这个问题。请仔细阅读源码,并填写划线部分缺少的代码。

#include <stdio.h>

int f3(const char* s, int begin, int end)
{
int sum = 0;
int i;
for(i=begin; i<end; i++){
if(s[i]==’ ') continue;
sum = sum * 10 + (s[i]-‘0’);
}
return sum;
}

int f2(const char* s, int begin, int end)
{
int p = begin;
int pro = 1;
while(1){
int p0 = p;
while(p!=end && s[p]!=’*’) p++;
pro *= _______________________________; //填空
if(p==end) break;
p++;
}
printf(“f2: pro=%d\n”, pro);
return pro;
}

int f(const char* s)
{
int p = 0;
int sum = 0;
while(1){
int p0 = p;
while(s[p]!=0 && s[p]!=’+’) p++;
sum += f2(s,p0,p);
if(s[p]==0) break;
p++;
}

return sum;
}

int main()
{
int x = f(“12+18+543+10”);
printf("%d\n", x);
return 0;
}

注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。

答案:f3(s,p0,p)



10.希尔伯特曲线

希尔伯特曲线是以下一系列分形曲线 Hn 的极限。我们可以把 Hn 看作一条覆盖 2^n × 2^n 方格矩阵的曲线,曲线上一共有 2^n × 2^n 个顶点(包括左下角起点和右下角终点),恰好覆盖每个方格一次。

[p1.png]

Hn(n > 1)可以通过如下方法构造:

  1. 将 Hn-1 顺时针旋转90度放在左下角
  2. 将 Hn-1 逆时针旋转90度放在右下角
  3. 将2个 Hn-1 分别放在左上角和右上角
  4. 用3条单位线段把4部分连接起来

对于 Hn 上每一个顶点 p ,我们定义 p 的坐标是它覆盖的小方格在矩阵中的坐标(左下角是(1, 1),右上角是(2^n, 2^n),从左到右是X轴正方向,从下到上是Y轴正方向),
定义 p 的序号是它在曲线上从起点开始数第几个顶点(从1开始计数)。

以下程序对于给定的n(n <= 30)和p点坐标(x, y),输出p点的序号。请仔细阅读分析源码,填写划线部分缺失的内容。

#include <stdio.h>

long long f(int n, int x, int y) {
if (n == 0) return 1;
int m = 1 << (n - 1);
if (x <= m && y <= m) {
return f(n - 1, y, x);
}
if (x > m && y <= m) {
return 3LL * m * m + f(n - 1, ________________ , m * 2 - x + 1); // 填空
}
if (x <= m && y > m) {
return 1LL * m * m + f(n - 1, x, y - m);
}
if (x > m && y > m) {
return 2LL * m * m + f(n - 1, x - m, y - m);
}
}

int main() {
int n, x, y;
scanf("%d %d %d", &n, &x, &y);
printf("%lld", f(n, x, y));

return 0;
}

注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。

在这里插入图片描述

答案:m+1-y

思路:找规律,m是现在的图的边长的一半,找旋转后小图中的的x,y与上一张图的x,y的关系

猜你喜欢

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