第七届蓝桥杯大赛个人赛省赛(软件类)\C语言B组--2016年

1、

煤球数目

有一堆煤球,堆成三角棱锥形。具体:

第一层放1个,

第二层3个(排列成三角形),

第三层6个(排列成三角形),

第四层10个(排列成三角形),

....

如果一共有100层,共有多少个煤球?

请填表示煤球总数目的数字。

思路:1 2 3 4 5 6……这一个等差数列的前n项和为(1+n)*n/2

第1层的煤球数目为1

第2层的煤球数目为1+2

第3层的煤球数目为1+2+3

……

第i层的煤球数组为(1+n)*n/2

答案:171700

A[i] = i+a[i-1]  i->1--100

//煤球数目
#include<stdio.h>
#define MAXN 102
int main(){
	int i,sum;
	int a[MAXN] = {0};
	a[1] = 1;
	sum = a[1];
	for(i=2;i<=100;i++){
		a[i] = a[i-1] + i;
		sum += a[i];
	}
	printf("%d",sum);
	return 0;
}  

2、

生日蜡烛

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。

现在算起来,他一共吹熄了236根蜡烛。

请问,他从多少岁开始过生日party的?

请填写他开始过生日party的年龄数。

思路:1 2 3 4 5 6……这一个等差数列的前n项和为(1+n)*n/2

设从a岁开始过生日,到了b岁一共吹熄了236根蜡烛。

即为:(a+b)(b-a+1)/2=236

答案:26

等差数列

#include<stdio.h>
int main(){
	int x,y;
	for(x=1;x<=100;x++){
		for(y=2;y<=100;y++){
			if((x+y)*(y-x+1) == 2*236)
				printf("%d",x);
		}
	}
	return 0;
} 

  

3、

凑算式

如图,这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?

思路:暴力解决,注意每个字母代表的数字不相等。

答案:29

//凑算数
#include<stdio.h>
int main(){
	int a,b,c,d,e,f,g,h,i;
	int count=0;
	for(a=1;a<=9;a++){
		for(b=1;b<=9;b++){
			if(a==b)
				continue;
			for(c=1;c<=9;c++){
				if(a==c||b==c)
					continue;
				for(d=1;d<=9;d++){
					if(a==d||b==d||c==d)
						continue;
					for(e=1;e<=9;e++){
						if(a==e||b==e||c==e||d==e)
							continue;
						for(f=1;f<=9;f++){
							if(a==f||b==f||c==f||d==f||e==f)
								continue;
							for(g=1;g<=9;g++){
								if(a==g||b==g||c==g||d==g||e==g||f==g)
									continue;
								for(h=1;h<=9;h++){
									if(a==h||b==h||c==h||d==h||e==h||f==h||g==h)
										continue;
									for(i=1;i<=9;i++){
										if(a==i||b==i||c==i||d==i||e==i||f==i||g==i||h==i)
											continue;
										if((10-a)*c*(g*100+h*10+i) == b*(g*100+h*10+i) + (d*100+e*10+f)*c)
											count++;
											
//										 if(a+1.0*b/c+(1.0*d*100+e*10*1.0+f*1.0)/(g*100*1.0+h*10*1.0+i*1.0)==10)
//										 	count++;
									} 
								}
							} 
						}
					} 
				}
			}
		}
	}
	printf("%d",count);
}

4、

快速排序

排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。

//快速排序
#include <stdio.h>
void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

int partition(int a[], int p, int r)
{
	int i = p;
	int j = r + 1;
	int x = a[p];
	while(1){
		while(i<r && a[++i]<x);
		while(a[--j]>x);
		if(i>=j) 
			break;
		swap(a,i,j);
	}
	swap(a,p,j);//______________________;
	return j;
}

void quicksort(int a[], int p, int r)
{
	if(p<r){
		int q = partition(a,p,r);
		quicksort(a,p,q-1);
		quicksort(a,q+1,r);
	}
}

int main()
{
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	quicksort(a, 0, N-1);
	for(i=0; i<N; i++) 
		printf("%d ", a[i]);
	printf("\n");
	return 0;
} 

 

  5、

抽签

X星球要派出一个5人组成的观察团前往W星。

其中:

A国最多可以派出4人。

B国最多可以派出2人。

C国最多可以派出2人。

....

那么最终派往W星的观察团会有多少种国别的不同组合呢?

下面的程序解决了这个问题。

数组a[] 中既是每个国家可以派出的最多的名额。

程序执行结果为:

DEFFF

CEFFF

CDFFF

CDEFF

CCFFF

CCEFF

CCDFF

CCDEF

BEFFF

BDFFF

BDEFF

BCFFF

BCEFF

BCDFF

BCDEF

....

(以下省略,总共101行)

#include <stdio.h>
#define N 6
#define M 5
#define BUF 1024

void f(int a[], int k, int m, char b[])
{	//k:
	int i,j;
	if(k==N){ 
		b[M] = 0;
		if(m==0) 
			printf("%s\n",b);
		return;
	}
	for(i=0; i<=a[k]; i++){	//对第k个国家,派出人数 0--a[k] 
		for(j=0; j<i; j++) 
			b[M-m+j] = k+'A';
		f(a,k+1,m-i,b);//______________________;  //填空位置
	}
}
int main()
{	
	int  a[N] = {4,2,2,1,1,3};	//a[]:每个国家可以派出的最多的名额 
	char b[BUF];
	f(a,0,M,b);
	return 0;
} 

6、

方格填数

如图,如下的10个格子,填入0~9的数字。要求:连续的两个数字不能相邻。

(左右、上下、对角都算相邻)一共有多少种可能的填数方案?

请填写表示方案数目的整数。

 

思路:这题方法很简单,暴力求解,依次向每个格子填数与已经填入的进行比较是否连续,即:是否两者之差的绝对值为1。比赛的时候一直在纠结,题干没有说明0~9的数字可以重复使用还是只能用一次,比赛时最后我按照可以重复使用提交的,不知道是不是正确。

答案:如果数字不可以重复使用,结果为1580

           如果数字可以重复使用,结果为206059714

//方格填数
#include<stdio.h>
#include<math.h> 
int flag[3][4];
int mp[3][4];
int visit[10];
int ans= 0;
void init(){
	int i,j;
	for(i=0;i<3;i++){
		for(j=0;j<4;j++){
			flag[i][j] = 1;
		}
	}
	flag[0][0] = 0;
	flag[2][3] = 0;
	for(i=0;i<10;i++)
		visit[i] = 0;
}
void Solve(){
	int i,j,k;
	int direction[8][2] = {
		{0,1},	//左 
		{0,-1},	//右 
		{1,0},
		{-1,0},
		{1,1},
		{1,-1},
		{-1,1},
		{-1,-1}
	};
	int temp = 1;
	for(i=0;i<3;i++){
		for(j=0;j<4;j++){
			if(flag[i][j] == 0)	
				continue;
			for(k=0;k<8;k++){
				int x,y;
				x = i + direction[k][0];
				y = j + direction[k][1];
				if(x < 0||x >=3 || y<0 || y>=4 || flag[x][y] == 0)	continue;
				if(abs(mp[x][y] - mp[i][j]) == 1)
					temp = 0;
			}
		}
	}
	if(temp ==1)
	  ans++;
}
void dfs(int n){
	int x,y,i;
	x = n / 4;	//行 
	y = n % 4;	//列 
	if(x == 3){	//递归出口,到dfs(12) 
		Solve();
		return;
	}
	if(flag[x][y] == 1){	//该处可以赋值0--9 
		for(i=0;i<10;i++){
			if(visit[i] == 0){	//
				visit[i] = 1;
				mp[x][y] = i;
				dfs(n+1);
				visit[i] = 0;
			}
		} 
	}
	else
		dfs(n+1); 
} 
int main(){
	init();	//对二维数组进行初始化
	dfs(0);	
	printf("%d\n",ans);	//输出方案数 
	return 0;
} 

7、

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。

现在你要从中剪下5张来,要求必须是连着的。

(仅仅连接一个角不算相连)

比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

 

 

思路:先找到5个数的组合,然后从第一个数字开始遍历,经过上下左右操作检测5个数是否都被访问一遍,如果5个数都可以遍历到则种类+1。

在原图中向上为-4,向下为+4,向左为-1,向右为+1,但是遇到3 4 5 7 8这种4+1=5但是这种情况不符合,所以重构一下原图:

这样,向上为-5,向下为+5,向左为-1,向右为+1,避免了每行最后一个+1后等于下一行第一个的情况。

答案:116

 

8、

四平方和

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多4个正整数的平方和。

如果把0包括进去,就正好可以表示为4个数的平方和。

比如:

5 = 0^2 + 0^2 + 1^2 + 2^2

7 = 1^2 + 1^2 + 1^2 + 2^2

(^符号表示乘方的意思)

对于一个给定的正整数,可能存在多种平方和的表示法。

要求你对4个数排序:

0 <= a <= b <= c <= d

并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法

程序输入为一个正整数N (N<5000000)

要求输出4个非负整数,按从小到大排序,中间用空格分开

例如,输入:

5

则程序应该输出:

0 0 1 2

再例如,输入:

12

则程序应该输出:

0 2 2 2

再例如,输入:

773535

则程序应该输出:

1 1 267 838

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 3000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

思路:该题为赛前参考题目里的一个代码填空题,暴力解决

//四平方和
#include<stdio.h>
int main(){
	int a,b,c,d;
	int N,sum = 0;
	scanf("%d",&N);
	for(a=0;a<=2237;a++){
		if(a*a > N)
			continue;
		for(b=a;b<=2237;b++){
			if(a*a + b*b > N)
				break;
			for(c=b;c<=2237;c++){
				if(a*a + b*b + c*c > N)
					continue;
				for(d=c;d<=2237;d++){
					if(a*a + b*b + c*c +d*d > N)
						break;
					sum = a*a+b*b+c*c+d*d;
					if(sum == N){
						printf("%d %d %d %d",a,b,c,d);
						return 0;	//
					}
				}
			}
		}
	}
	return 0;
}   

9、

交换瓶子

有N个瓶子,编号 1 ~ N,放在架子上。

比如有5个瓶子:

2 1 3 5 4

要求每次拿起2个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

1 2 3 4 5

 

对于这么简单的情况,显然,至少需要交换2次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。

输入格式为两行:

第一行: 一个正整数N(N<10000), 表示瓶子的数目

第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。

输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。

例如,输入:

5

3 1 2 5 4

程序应该输出:

3

再例如,输入:

5

5 4 3 2 1

程序应该输出:

2

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

思路:类似选择排序。

//交换瓶子
#include<stdio.h>
#define MAXN 20

int main(){
	int i,j,n;
	int count = 0,min_n;
	int a[MAXN];
	scanf("%d",&n);
	
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<n;i++){
		min_n = i;
		for(j=i+1;j<n;j++){
			if(a[min_n] > a[j])
				min_n = j;
		}
		if(min_n != i){
			count++;
			int t=a[i];
            a[i]=a[min_n];
            a[min_n]=t;
		}
	}
	printf("%d",count);
	return 0;
}

10、

最大比例

X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。

并且,相邻的两个级别间的比例是个固定值。

也就是说:所有级别的奖金数构成了一个等比数列。比如:

16,24,36,54

其等比值为:3/2

现在,我们随机调查了一些获奖者的奖金数。

请你据此推算可能的最大的等比值。

输入格式:

第一行为数字N(N<=100),表示接下的一行包含N个正整数

第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额

要求输出:

一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数

测试数据保证了输入格式正确,并且最大比例是存在的。

例如,输入:

3

1250 200 32

程序应该输出:

25/4

再例如,输入:

4

3125 32 32 200

程序应该输出:

5/2

再例如,输入:

3

549755813888 524288 2

程序应该输出:

4/1

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 3000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

思路:所有级别的奖金数构成了一个等比数列,公比相同。例如,

1  2  4  8  16  32这一个等比数列。

因为题意为随机调查一些获奖者的奖金数,即,抽到的项可能为连续的项也可能是不连续的项。

如果抽到1  2  4,这三个连续项,公比为4/2=2/1=2。

如果抽到1  4  8,这三个不连续的项,则相邻项的商为8/4=2, 4/1=4,再从4和2中取最大公约数就为最后的结果。相当于1为数列第一项,4为数列第三项,8为数列第四项,即1=a1  4=a1*r^2   8=a1*r^3,

8/4=r      4/1=r^2    从r和r^2中得到公比,即为最大的比例。

 

 

 

posted @ 2019-11-26 12:07  Hqx_curiosity  阅读(551)  评论(0编辑  收藏  举报