2016年第七届蓝桥杯C/C++程序设计本科B组省赛题目汇总

1.煤球数目
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),

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

请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解题思路:

#include <iostream>
using namespace std;
int main(){
    int sum=0,n;
    cin >> n;
    for(int i = 1;i <= n;i++)
    {
        sum += i * (i + 1) / 2;
    }
    cout << sum << endl;
    return 0;
}//171700

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
解题思路1:

#include <iostream>
using namespace std;
int main(){
    for(int i = 1;i <= 100;i++){
        for(int j = i;j <= 100;j++){
            if((i + j) * ( j - i + 1) / 2 == 236)
                cout << i << " " << j << endl;
        }       
    }
    return 0;
}//26

3.凑算式(全排列)

     B      DEF
A + --- + ------- = 10
     C      GHI

(如果显示有问题,可以参见【图1.jpg】)

在这里插入图片描述

这个算式中AI代表19的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

示例:意思为求1,2,3,4的全排列:next_permutation(a,a+4)
解题思路1:

#include<iostream>
#include<algorithm> 
using namespace std;
double a[9]={1,2,3,4,5,6,7,8,9};
int c;
int main(){
    while(next_permutation(a,a+9)){
        if(a[0] + a[1] / a[2] + ( a[3] * 100 + a[4] * 10 + a[5] ) / ( a[6] * 100 + a[7] * 10 + a[8]) == 10.0) 
            c++;
    }
    cout << c << endl; 
    return 0;
} //29

解题思路2:

#include<iostream>
using namespace std;
int a[9] = {0};
int ans = 0;
bool judge(int a[]){//判断是否算式和为10
    double x = a[0] + a[1] * 1.0 / a[2] + ( a[3] * 100 + a[4] * 10 + a[5]) * 1.0 / ( a[6] * 100 + a[7] * 10 + a[8]);
    if(x == 10.0) return 1;
    return 0;
}
bool check(int num){//检测a[num]是否有重复
    for(int i = num-1;i >= 0;i--){ 
        if(a[i] == a[num]) return 0;
    }
    return 1;
}
void dfs(int num){//就是最基本的9个数全排列,在结束条件里用judge()做判断
    if(num>8){
        if(judge(a))
        ans++;
        return;
    }
    for(int i = 1;i < 10;i++){
        a[num] = i;
        if(check(num)){
            dfs(num+1);
        }
    }
}
int main(){
    dfs(0);
    cout << ans;
    return 0;
}

解题思路3:

#include<iostream> 
using namespace std; 
int main(void){ 
    int count = 0; 
    for(int a = 1;a < 10;a++){ 
        for(int b = 1;b < 10;b++){ 
            if(a == b) continue; 
            for(int c = 1;c < 10;c++){ 
                if(a == c || c == b) continue; 
                for(int d = 1;d < 10;d++){ 
                    if(a == d || d == b || c == d)continue; 
                    for(int e = 1;e < 10; e++){ 
                        if(e == a || e == b || e == c || e == d)continue; 
                        for(int f = 1; f < 10;f++){ 
                            if(f == a || f == b || f == c || f == d || f == e)continue; 
                            for(int g = 1;g < 10;g++){ 
                                if(g == a || g == b || g == c || g == d || g == e || g == f)continue; 
                                for(int h = 1;h < 10;h++){ 
                                    if(h == a || h == b|| h == c || h == d || h == e || h == f || h == g)continue; 
                                    for(int i = 1; i < 10;i++){ 
                                        if(i == a || i == b || i == c || i == d || i == e || i == f || i == g || i == h)continue; 
                                        int t1 = a * c * ( 100 * g + 10 * h + i ); 
                                        int t2 = b * (100 * g + 10 * h + i); 
                                        int t3 = c * (100 * d + 10 * e + f); 
                                        int t4 = 10 * c * (100 * g + 10 * h + i); 
                                        if( t1 + t2 + t3 == t4)count++; 
                                    } 
                                } 
                            } 
                        } 
                    } 
                } 
            } 
        }
    }
    cout << count << endl; 
    return 0; 
}

4.快速排序
排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。

其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。

这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。

下面的代码是一种实现,请分析并填写划线部分缺少的代码。

#include <stdio.h>
#include <stdlib.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){//分区0 11
    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);//填空   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[]){
	int i,j;
	if(k == N){
		b[M] = 0;
		if(m == 0) printf("%s\n",b);
		return;
	}
	for(i = 0; i <= a[k]; i++){
		for(j = 0; j < i; j++) b[M - m + j] = k + 'A';//数字加上 英文字符表示 对应的 
//		printf("%s\n", b[i]);  //填空位置
		f(a,k+1,m-i,b); 
	}
}
int main(){	
	int a[N] = {4,2,2,1,1,3};
	char b[BUF];
	f(a,0,M,b);
	return 0;
}

仔细阅读代码,填写划线部分缺少的内容。
注意:不要填写任何已有内容或说明性文字。

解题思路:
思路:一共选M个人,m经过选择记录剩下可选人数,M-m为已经选择的人数
M-m+j为新加入的人在b数组中的下标。这题在填空之后可以利用总共101行这个条件进行验证,即:在f函数每次printf输出的时候进行统计个数,最后输出sum检测是否为101。注意不要多填分号。
答案:f(a,k+1,m-i,b),因为这里i = j .应该 f(a,k+1,m-j,b)也可以。
6.方格填数
如下的10个格子

   +--+--+--+
   |  |  |  |
+--+--+--+--+
|  |  |  |  |
+--+--+--+--+
|  |  |  |
+--+--+--+

在这里插入图片描述

(如果显示有问题,也可以参看【图1.jpg】)

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

解题思路:

#include <iostream>
#include <algorithm>
using namespace std;
int a[11]= {11111,0,1,2,3,4,5,6,7,8,9};
int judge(){
    if(abs(a[1]-a[2]) == 1 || abs(a[1]-a[4]) == 1 || abs(a[1]-a[5]) == 1 || abs(a[1] - a[6]) == 1)
        return 0;
    else if(abs(a[2]-a[5]) == 1 || abs(a[2]-a[6]) == 1 || abs(a[2]-a[7]) == 1 || abs(a[2]-a[3]) == 1)
        return 0;
    else if(abs(a[3]-a[6]) == 1 || abs(a[3]-a[7]) == 1)
        return 0;
    else if(abs(a[4]-a[5]) == 1 || abs(a[4]-a[8]) == 1 || abs(a[4]-a[9]) == 1)
        return 0;
    else if(abs(a[5]-a[6]) == 1 || abs(a[5]-a[8]) == 1 || abs(a[5]-a[9]) == 1 || abs(a[5]-a[10]) == 1)
        return 0;
    else if(abs(a[6]-a[7]) == 1 || abs(a[6]-a[9]) == 1 || abs(a[6]-a[10]) == 1)
        return 0;
    else if(abs(a[7]-a[10]) == 1)
        return 0;
    else if(abs(a[8]-a[9]) == 1)
        return 0;
    else if(abs(a[9]-a[10]) == 1)
        return 0;
    return 1;
}
int main(){
    int sum = 0;
    do{      
        if(judge())
            sum++;
	}while(next_permutation(a + 1,a + 11));
    cout << sum;
    return 0;
}

解题思路2:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int flag[3][4]; //表示哪些可以填数
int mpt[3][4]; //填数
bool 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;
}
void Solve(){
	int dir[8][2] = { 0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};
	int book = true;
	for(int i = 0 ; i < 3 ; i ++){
		for(int j = 0 ; j < 4; j ++){
			//判断每个数周围是否满足
			if(flag[i][j] == 0)continue;
			for( int k = 0 ; k < 8 ; k ++){
				int x,y;
				x = i + dir[k][0];
				y = j + dir[k][1];
				if(x < 0 || x >= 3 || y < 0 || y >= 4 || flag[x][y] == 0) continue;
				if(abs(mpt[x][y] - mpt[i][j]) == 1)  book = false;
			}
		}
	}
	if(book){
		ans++;	
	}
}
void dfs(int index){
	int x,y;
	x = index / 4;
	y = index % 4;
	if( x == 3){
		Solve();
		return;
	}
	if(flag[x][y]){
		for(int i = 0 ; i < 10 ; i ++){
			if(!visit[i]){
				visit[i] = true;
				mpt[x][y] = i;
				dfs(index+1);
				visit[i] = false;
			}
		}
	}else{
		dfs(index+1);
	}
}
int main(){
	init();
	dfs(0);
	printf("%d\n",ans);
	return 0;
}

7.剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
在这里插入图片描述
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
在这里插入图片描述在这里插入图片描述

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

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

8.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

解题思路:

#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
    for(int a = 0;a <= 2237;a++){
        if( a * a > n) continue;
        for(int b = a; b <= 2237;b++){
            if( a * a + b * b > n) break;
            for(int c = b;c <= 2237;c++){
                if( a * a + b * b + c * c > n) break;
                    for(int d = c;d <= 2237;d++){
                        if(a * a + b * b + c * c + d * d > n) break;
                        if(a * a + b * b + c * c + d * d == n){
                            cout << a << " " << b << " " << c << " " << d <<endl;
                            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

解题思路:
思路:因为要交换次数最少,所以自然是每次选中一个瓶子,把它交换到它该在的位置,这样次数最少,那么就只是一个选择排序问题了。

#include <iostream>
using namespace std;
int main(){
    int n,a[10000],sum=0;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a[i];
    }
    int minn;
    for(int i = 0; i < n; i++){
        minn = i;
        for(int j = i + 1; j < n; j++){
            if( a[minn] > a[j]){
                minn = j;
            }
        }
        if(minn != i){
            sum++;
            int t = a[i];
            a[i] = a[minn];
            a[minn] = t;
        }
    }
    cout << sum << endl;
    return 0;
}

最大比例
X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:
16,24,36,54
其等比值为:3/2

现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。

输入格式:
第一行为数字 N (0<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
一般没有这个水平做到这儿来 放弃了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值