2014年第五届蓝桥杯总结与思考(C/C++本科B组)

1.啤酒和饮料

啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。
我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。
注意:答案是一个整数。

#include<stdio.h>

int main() {
	double sum;
	for(int i = 1;i < 100 ; i++) {
		for(int j = 1;j < 100 ; j++) {
			sum = i * 2.3 + j * 1.9;
			if(i < j && sum == 82.3) 
				printf("%d\n", i);
		}
	}
	return 0;
} 

2.切面条

一根高筋拉面,中间切一刀,可以得到2根面条。
如果先对折1次,中间切一刀,可以得到3根面条。
如果连续对折2次,中间切一刀,可以得到5根面条。
那么,连续对折10次,中间切一刀,会得到多少面条呢

#include<stdio.h>

int main() {
	int n = 1;
	for(int i = 0; i < 10; i++) {
		n *= 2;
	}
	printf("%d", n + 1);  
	return 0;
}

3.李白打酒

话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。

刚看到这道题的时候,感觉这不挺简单的的嘛,然后错了!!!(๑ó﹏ò๑)

#include<stdio.h>

int count = 0;
void li(int hua, int dian, int jiu){
	if(dian > 5 || hua > 10) return ;
	if (dian == 5 && hua == 10 && jiu == 0){
		count++;
		return;
	}
	li(hua, dian +1, jiu * 2);
    li(hua + 1, dian, jiu - 1);  
}
int main() {
	li(0, 0, 2);
	printf("%d", count);
	return 0;
}


想了好一会才发现我少了一个判断,就是遇到的遇到花的的次数不满十次或者遇到店的次数不满五次酒就没有了

#include<stdio.h>

int count = 0;
void li(int hua, int dian, int jiu){
	if(dian > 5 || hua > 10) return ;
	if((hua< 10 && jiu <= 0) || (dian < 5 && jiu <= 0)) return;
	if (dian == 5 && hua == 10 && jiu == 0){
		count++;
		return;
	}
	li(hua, dian +1, jiu * 2);
    li(hua + 1, dian, jiu - 1);  
}
int main() {
	li(0, 0, 2);
	printf("%d", count);
	return 0;
}


4.史丰收速算

史丰收速算法的革命性贡献是:从高位算起,预测进位。不需要九九表,彻底颠覆了传统手算!
速算的核心基础是:1位数乘以多位数的乘法。
其中,乘以7是最复杂的,就以它为例。
因为,1/7 是个循环小数:0.142857…,如果多位数超过 142857…,就要进1
同理,2/7, 3/7, … 6/7 也都是类似的循环小数,多位数超过 n/7,就要进n
下面的程序模拟了史丰收速算法中乘以7的运算过程。
乘以 7 的个位规律是:偶数乘以2,奇数乘以2再加5,都只取个位。
乘以 7 的进位规律是:
满 142857… 进1,
满 285714… 进2,
满 428571… 进3,
满 571428… 进4,
满 714285… 进5,
满 857142… 进6

 请分析程序流程,填写划线部分缺少的代码。
//计算个位 
int ge_wei(int a)
{
	if(a % 2 == 0)
		return (a * 2) % 10;
	else
		return (a * 2 + 5) % 10;	
}

//计算进位 
int jin_wei(char* p)
{
	char* level[] = {
		"142857",
		"285714",
		"428571",
		"571428",
		"714285",
		"857142"
	};
	
	char buf[7];
	buf[6] = '\0';
	strncpy(buf,p,6);
	
	int i;
	for(i=5; i>=0; i--){
		int r = strcmp(level[i], buf);
		if(r<0) return i+1;
		while(r==0){
			p += 6;
			strncpy(buf,p,6);
			r = strcmp(level[i], buf);
			if(r<0) return i+1;
			______________________________;  //填空
		}
	}
	
	return 0;
}

//多位数乘以7
void f(char* s) 
{
	int head = jin_wei(s);
	if(head > 0) printf("%d", head);
	
	char* p = s;
	while(*p){
		int a = (*p-'0');
		int x = (ge_wei(a) + jin_wei(p+1)) % 10;
		printf("%d",x);
		p++;
	}
	
	printf("\n");
}

int main()
{
	f("428571428571");
	f("34553834937543");		
	return 0;
}

由代码可以看出填空应写 if(r > 0)时 ,return 返回一个什么值
由题目可以看出r > 0时, level[i]> buf ,从题目中提到的进位规律可以得出return 返回i,所以填空处应写if(r > 0) return i;

5.打印图形

小明在X星球的城堡中发现了如下图形和文字:

rank=3

   * 
  * * 
 *   *  
* * * *

rank=5

               *                                                      
              * *                                                     
             *   *                                                    
            * * * *                                                   
           *       *                                                  
          * *     * *                                                 
         *   *   *   *                                                
        * * * * * * * *                                               
       *               *                                              
      * *             * *                                             
     *   *           *   *                                            
    * * * *         * * * *                                           
   *       *       *       *  
  * *     * *     * *     * *  
 *   *   *   *   *   *   *   * 
* * * * * * * * * * * * * * * *  

ran=6

                               *                                      
                              * *                                     
                             *   *                                    
                            * * * *                                   
                           *       *                                  
                          * *     * *                                 
                         *   *   *   *                                
                        * * * * * * * *                               
                       *               *                              
                      * *             * *                             
                     *   *           *   *                            
                    * * * *         * * * *                           
                   *       *       *       *                          
                  * *     * *     * *     * *                         
                 *   *   *   *   *   *   *   *                        
                * * * * * * * * * * * * * * * *                       
               *                               *                      
              * *                             * *                     
             *   *                           *   *                    
            * * * *                         * * * *                   
           *       *                       *       *                  
          * *     * *                     * *     * *                 
         *   *   *   *                   *   *   *   *                
        * * * * * * * *                 * * * * * * * *               
       *               *               *               *              
      * *             * *             * *             * *             
     *   *           *   *           *   *           *   *            
    * * * *         * * * *         * * * *         * * * *           
   *       *       *       *       *       *       *       *          
  * *     * *     * *     * *     * *     * *     * *     * *         
 *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *        
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *       

                                            
 小明开动脑筋,编写了如下的程序,实现该图形的打印。
#define N 70

void f(char a[][N], int rank, int row, int col)
{
	if(rank==1){
		a[row][col] = '*';
		return;
	}
	
	int w = 1;
	int i;
	for(i=0; i<rank-1; i++) 
		w *= 2;
	
	____________________________________________;
	f(a, rank-1, row+w/2, col);
	f(a, rank-1, row+w/2, col+w);
}

int main()
{
	char a[N][N];
	int i,j;
	for(i=0;i<N;i++)
	for(j=0;j<N;j++) a[i][j] = ' ';
	
	f(a,6,0,0);
	
	for(i=0; i<N; i++){
		for(j=0; j<N; j++) printf("%c",a[i][j]);
		printf("\n");
	}
	
	return 0;
}

应填f(a, rank-1, row, col+w/2);

6.奇怪的分式


上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:

1/4 乘以 8/5

小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图)
老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?

请写出所有不同算式的个数(包括题中举例的)。
显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!

#include<stdio.h>

int main() {
	int a, b, c, d;
	int count = 0;
	for(a = 1; a < 10; a++){
		for(b = 1; b < 10; b++){
			if(a == b) continue;
			for(c = 1; c < 10; c++) {
				for(d = 1; d < 10; d++) {
					if(c == d) continue;
					if((a * c) * 1.0 / (b * d) == (a * 10 + c) * 1.0 / (b * 10 + d) )   //一定不要忘记乘1.0!!!
					count++;
				}
			}
		}
	}
	printf("%d\n", count);
	return 0;
}

7.六角填数

在这里插入图片描述

如图,所示六角形中,填入1~12的数字。
使得每条直线上的数字之和都相同。
图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?

看到这个题,这不就是全排列嘛,简单,就是有点费手

#include<stdio.h>

int main() {
	int a, b, c, d, e, f, g, h, i;
	for(a = 2; a < 13; a++)
		if(a != 3 && a != 8)
	for(b = 2 ; b < 13; b++)
		if(b != 3 && b != 8 && a != b)
	for(c = 2 ; c < 13; c++)
		if(c != 3 && c != 8 && c != b && c != a)
	for(d = 2 ; d < 13; d++)
		if(d != 3 && d != 8 && c != d && d != a && d != b)
	for(e = 2 ; e < 13; e++)
		if(e != 3 && e != 8 && e != a && e != b && e != d && e != c)
	for(f = 2 ; f < 13; f++)
		if(f != 3 && f != 8 && f != a && f != b && f != c && f != d && f != e) 
	for(g = 2 ; g < 13; g++)
		if(g != 3 && g != 8 && g != a && g != b && g != c && g != d && g != e && g != f)
	for(h = 2 ; h < 13; h++)
		if(h != 3 && h != 8 && h != a && h != b && h != c && h != d && h != e && h != f && h != g)
	for(i = 2 ; i < 13; i++){
		if(i != 3 && i != 8 && i != a && i != b && i != c && i != d && i != e && i != f && i != g && i != h){
			int m = 1 + a + d + f,
				n = 8 + a + b + c,
				x = 1 + b + e + i,
				q = 8 + d + g + 3,
				p = c + e + h + 3,
				t = f + g + h + i;
			if(m == n && n == x && x == q && q == p && p == t)
				printf("%d\n", d);
		}
	}					
	return 0;
}

**感觉这个有那么亿点点蠢 **
然后我get了一个新的函数 全排列函数 next_permutation()

#include<stdio.h>
#include<algorithm>
using namespace std;
int main() {
	int num[7];
	int a[13] = {0, 1, 8, 2, 4, 5, 6, 7, 9, 10, 11, 12, 3};
	while(next_permutation(a + 3, a + 12)) {// a 数组中前三个(0,1,8)和最后一个(3)不参与排列 
		num[1] = a[1] + a[3] + a[6] + a[8];
		num[2] = a[1] + a[4] + a[7] + a[11];
		num[3] = a[2] + a[3] + a[4] + a[5];
		num[4] = a[2] + a[6] + a[9] + a[12];
		num[5] = a[5] + a[7] + a[10] + a[12];
		num[6] = a[8] + a[9] + a[10] + a[11];
		if(num[1]==num[2] && num[2]==num[3] && num[3]==num[4] && num[4]==num[5] && num[5]==num[6])
			printf("%d\n", a[6]);
	} 
	return 0;
}

8.蚂蚁感冒

长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。
每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。
当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。
这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

 请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

【数据格式】

第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。

接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。

要求输出1个整数,表示最后感冒蚂蚁的数目。

例如,输入:
3
5 -2 8
程序应输出:
1

再例如,输入:
5
-10 8 -20 12 25
程序应输出:
3

代码如下
#include<stdio.h>
#include<math.h> 

int main() {
	int n;
	int count = 1;  //感冒的蚂蚁最开始有一个; 
	int num = 0, cnt = 0;
	scanf("%d", &n);
	int a[n];
	for(int i = 0; i < n; i++) {      //首个感冒蚂蚁位置为a[0]; 
		scanf("%d", &a[i]);
	}
	for(int i = 1; i < n; i++) {           //abs()函数求出蚂蚁在杆子上的位置 
		if(abs(a[0]) < abs(a[i]) && a[i] < 0)   //当在首个蚂蚁右侧并且反向 必感冒
		   cnt++;                 
       	if(abs(a[0]) > abs(a[i]) && a[i] > 0)   //当在首个蚂蚁右侧并且反向 必感冒
		   num++;                 
	}
	if(a[0] > 0 && cnt != 0 || a[0] < 0 && num != 0)  // 判断是否有蚂蚁被传染 
		count += cnt + num ;
	printf("%d\n", count);
	return 0;
}

9.地宫取宝

X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。

【数据格式】

输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。

例如,输入:
2 2 2
1 2
2 1
输出:
2

再例如,输入:
2 3 2
1 2 3
2 1 5
输出:
14

思路分析: 深度搜索DFS(ಥ_ಥ)

#include<stdio.h> 
#define MOD 1000000007

int n, m, k;
int d[50][50]; 
long long ans;
void dfs(int x, int y, int max, int cnt){	
	if(x == n || y== m || cnt > k) return;
	int bao = d[x][y];
	if(x == n - 1 && y == m-1) {               //最后一个格子
		if(cnt == k) {
			ans++;
			if(ans > MOD) ans %= MOD;
		}
		if(cnt == k - 1 && bao > max) {
			ans++;
			if(ans > MOD) ans %= MOD;
		}
	} 	
	if(bao > max) {                             //可以取 	
		dfs(x, y+1, bao, cnt + 1);              //向右走 
		dfs(x+1, y, bao, cnt + 1);              //向下走 
	}
	//不能取,或者不取 
	 dfs(x, y+1, max, cnt);           //向右走 
	 dfs(x+1, y, max, cnt);           //向下走 
}
int main(){
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < n ; i++)
    	for(int j = 0; j < m; j++){
    		scanf("%d", &d[i][j]);
	}
	dfs(0, 0, -1, 0);           //第一个点的价值可能是0,所以bao初值为-1; 
	printf("%d\n", ans);
	return 0;
}

10.小朋友排队

n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。
每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。

【数据格式】

输入的第一行包含一个整数n,表示小朋友的个数。
第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。

例如,输入:
3
3 2 1
程序应该输出:
9

【样例说明】
首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。

看着题目像一道很简单的题结果我写了一个多小时才写出来,写的我好难受(╥﹏╥),但是写出来了还是很快乐的

思路: 看见题目描述相信第一想法是冒泡排序,但是非常重要的问题是冒泡并不能保证当前交换方式使不高兴程度和最小!
然后我用了求逆序数的方法,然后再把每个小朋友的不高兴值相加

#include<stdio.h>
#define maxn 100

int a[maxn];
int f[maxn] = {0};
int main() {
	int n;
	int count = 0, sum = 0;
	scanf("%d", &n);
	for(int i = 0; i < n; i++) {
		scanf("%d", &a[i]);
	}
	for(int i = 0; i < n; i++) {
		
		for(int j = i+1; j < n; j++){
			if(a[i] > a[j]){
				f[a[i]]++;
				f[a[j]]++;
			}
		}
	}
	for(int i = 0; i < n; i++){
		count  = 0;
		for(int j = f[a[i]]; j > 0; j--){
			count += j;
		}
		sum += count;
	}
	printf("%d\n", sum);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值