2015年第六届蓝桥杯C/C++B组省赛题目及答案1

01. 奖券数目

有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利。
虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求。某抽奖活动的奖券号码是5位数(10000-99999),要求其中不要出现带“4”的号码,主办单位请你计算一下,如果任何两张奖券不重号,最多可发出奖券多少张。

请提交该数字(一个整数),不要写任何多余的内容或说明性文字。

答案:52488
无脑解法:就是每个数逐位排除

#include <iostream>
using namespace std;

int main()
{
	long long a = 10000;
	long long ans = 0;
	for (int i = a; i <= 99999; i++)
	{
		a = i; //这个很重要,不要忘了 
		int gewei = a%10;
		if (gewei != 4)
		{
			a = a/10;
			int shiwei = a%10;
			if (shiwei != 4)
			{
				a = a/10;
				int baiwei = a%10;
				if (baiwei != 4)
				{
					a = a/10;
					int qianwei = a%10;
					if (qianwei != 4)
					{
						a = a/10;
						int wanwei = a%10;
						if (wanwei != 4)
						{
							a = a/10;
							if (a != 4)
							{
								ans++;
							}
						}
					}
				}
			}
		}
	}
	cout << ans << endl;
}

优化:用函数解决,把数字转为字符串(注:i2s这个函数要记住)

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

void i2s(int num, string &str) //这个函数要会背 
{
	stringstream ss;  //用到头文件<sstream>
	ss << num;
	ss >> str; 
}

int main()
{
	int ans = 0;
	for (int i = 10000; i <= 99999; i++)
	{
		string s;
		i2s(i,s);
		if (s.find('4') == string::npos) //string:npos是个特殊值,说明查找没有匹配
		{
			ans++;
		}
	}
	cout << ans << endl;
	return 0;
}

02. 星系炸弹

在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。 每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。

请填写该日期,格式为 yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19
请严格按照格式书写。不能出现其它文字或符号。

答案:2017-08-05

解:拿代码来计算:

#include <iostream>
using namespace std;
int main()
{
	int i = 21+31; //2014年剩下的时间
	i += 365; //2015年
	i += 366; //2016年
//	i += 365; //先尝试加完整个2017年,输出1148,超过一千了,所以在2017年爆炸,下面逐月加下去
//	i += 31+28+31+30+31+30+31+31; //尝试加到8月,再输出,得到1026,所以说明在8月份
	i +=  31+28+31+30+31+30+31+5; //31-26=5 ,所以尝试+5,输出检查,结果正好为1000,所以就是在5号 
	cout << i << endl;
	return 0; 
}

03. 三羊献瑞

观察下面的加法算式:

  祥 瑞 生 辉
+ 三 羊 献 瑞
------------------- 
三 羊 生 瑞 气

(如果有对齐问题,可以参看【图1.jpg】)

其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。

请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。
在这里插入图片描述

答案:1085

无脑解法:

#include <iostream>
using namespace std;

int main()
{
	int a,b,c,d,e,f,g,h;
	for (a = 0; a <= 9; a++)
	{
		for (b = 0; b <= 9; b++)
		{
			if (b != a) //这一个注意不能漏,字不同,代表的数字也不能相同 
			{
				for (c = 0; c <= 9; c++)
				{
					if (c!=a && c!=b)
					{
						for (d = 0; d <= 9; d++)
						{
							if (d!=a && d!= b && d!= c)
							{
								for (e = 0; e <= 9; e++)
								{
									if (e!=a && e!= b && e!= c && e!=d)
									{
										for (f = 0; f <= 9; f++)
										{
											if (f!=a && f!= b && f!= c && f!=d && f!=e)
											{
												for (g = 0; g <= 9; g++)
												{
													if (g!=a && g!= b && g!= c && g!=d && g!=e && g!=f)
													{
														for (h = 0; h <= 9; h++)
														{
															if (h!=a && h!= b && h!= c && h!=d && h!=e && h!=f && h!=g)
															{
																int i = e*1000 + d*100 + f*10 + g;
																int j = a*1000 + b*100 + c*10 + d;
																int k = a*10000 + b*1000 + f*100 + d*10 + h;
																if((i+j) == k)
																{
																	cout << a << " " << b << " " << c << " " << d  << " " << e << " " << f << " " << g << " " << h << endl; 
																}
															}
															
														} 
													}
													
												}
											}
											
										}
									}
									
								}
							}
							
						}
					}
					
				}
			}
			
		}
	}
	return 0;
}

输出:
在这里插入图片描述
因为是四位数,所以选“1085”

优化:

#include <iostream>
using namespace std;

int main()
{
	for (int b = 2; b < 9; b++) //因为f=0,e=1,a=9,所以其它数不能是这三个数,这点要注意!! 
	{
		for (int d = 2; d < 9; d++)
		{
			if (b == d)
			{
				continue;
			}
			for (int g = 2; g < 9; g++)
			{
				if (g == b || g == d)
				{
					continue;
				}
				int c = b+1;
				if (c == b || c == d || c== g || c==9)
				{
					continue;
				}
				if (c+g <= 10)
				{
					continue;
				}
				int sum = 9000 + b*100 + c*10 + d + 1000 + g*10 + b;
				for (int h = 2; h < 9; h++)
				{
					if (h == b || h == d || h == c || h == g)
					{
						continue;
					}
					if (sum <= (10000+c*100+b*10+h) && sum >= (10000+c*100+b*10+h))
					{
						cout << "10" << g << b << endl; 
					}
				}
			}
		}
	}
	return 0;
}

在这里插入图片描述

04. 格子中输出

StringInGrid函数会在一个指定大小的格子中打印指定的字符串。 要求字符串在水平、垂直两个方向上都居中。 如果字符串太长,就截断。
如果不能恰好居中,可以稍稍偏左或者偏上一点。

下面的程序实现这个逻辑,请填写划线部分缺少的代码。

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

void StringInGrid(int width, int height, const char* s)
{
    int i,k;
    char buf[1000];
    strcpy(buf, s);
    if(strlen(s)>width-2) buf[width-2]=0;
    
    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n");
    
    for(k=1; k<(height-1)/2;k++){
        printf("|");
        for(i=0;i<width-2;i++) printf(" ");
        printf("|\n");
    }
    
    printf("|");
    
    printf("%*s%s%*s",_____________________________________________);  //填空
              
    printf("|\n");
    
    for(k=(height-1)/2+1; k<height-1; k++){
        printf("|");
        for(i=0;i<width-2;i++) printf(" ");
        printf("|\n");
    }    
    
    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n");    
}

int main()
{
    StringInGrid(20,6,"abcd1234");
    return 0;
}

对于题目中数据,应该输出:
在这里插入图片描述
(如果出现对齐问题,参看下图所示)

在这里插入图片描述
注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

思路:
先把横线的那一行注释掉,然后运行一遍,看需要我们补充输出的是什么,再进行分析

答案:(width-strlen(buf)-2)/2," “,buf,(width-strlen(buf)-2)/2,” "

分析:考点就是%*

完整代码:

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

void StringInGrid(int width, int height, const char* s)
{
    int i,k;
    char buf[1000];
    strcpy(buf, s);
    if(strlen(s)>width-2) buf[width-2]=0; //如果字符串太长,就截断
    
    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n"); //输出第一条横边 
    
    for(k=1; k<(height-1)/2;k++){
        printf("|"); //左边竖线的上半部分 
        for(i=0;i<width-2;i++) printf(" "); //中间的空格 
        printf("|\n"); //右边竖线的上半部分 
    } //这里就是解决上半空白部分 
    
    printf("|");
    
//    printf("%*s%s%*s",_____________________________________________);  //填空
// *号代表的是宽度,宽度表示有两种方式,一是直接填数字,二是用*号表示,
//*号可表示占位符,具体*号表示占多少,在外面写,例如printf("%*s\n",5,'1'); 空格到第五个的时候才输出字符串1
//由此可推出,横线上填的是字符串和字符串前后的空格数 
    printf("%*s%s%*s",(width-strlen(buf)-2)/2," ",buf,(width-strlen(buf)-2)/2," ");
	//*号代表(width-strlen(buf)-2)/2," "代表*后面的s          
    printf("|\n");
    
    for(k=(height-1)/2+1; k<height-1; k++){
        printf("|");
        for(i=0;i<width-2;i++) printf(" ");
        printf("|\n");
    }    
    
    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n");    
}

int main()
{
    StringInGrid(20,6,"abcd1234");
    return 0;
}

05. 九数组分数

1,2,3…9 这九个数字组成一个分数,其值恰好为1/3,如何组法?

下面的程序实现了该功能,请填写划线部分缺失的代码。

#include <stdio.h>

void test(int x[]) {
    int a = x[0]*1000 + x[1]*100 + x[2]*10 + x[3];
    int b = x[4]*10000 + x[5]*1000 + x[6]*100 + x[7]*10 + x[8];
    
    if(a*3==b) printf("%d / %d\n", a, b); }

void f(int x[], int k) {
    int i,t;
    if(k>=9){
        test(x);
        return;
    }
    
    for(i=k; i<9; i++){
        {t=x[k]; x[k]=x[i]; x[i]=t;}
        f(x,k+1);
        _____________________________________________ // 填空处
    } }
     int main() {
    int x[] = {1,2,3,4,5,6,7,8,9};
    f(x,0);    
    return 0; }

注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

分析:本题是典型的全排列,要记住!

答案:{t=x[k]; x[k]=x[i]; x[i]=t;}

在这里插入图片描述

#include <stdio.h>

void test(int x[])
{
    int a = x[0]*1000 + x[1]*100 + x[2]*10 + x[3];
    int b = x[4]*10000 + x[5]*1000 + x[6]*100 + x[7]*10 + x[8];
    
    if(a*3==b) printf("%d / %d\n", a, b);
} //检验x[] 

void f(int x[], int k)  //这个要会背,递归框架,全排列 
{
    int i,t;
    if(k>=9){ //形成一个排列 
        test(x); //检查 
        return; 
    }  //出口 
    
    for(i=k; i<9; i++){ //从k开始,将后续所有的字符都尝试着换到i这个位置 
        {t=x[k]; x[k]=x[i]; x[i]=t;} //交换,确定这一位 
        f(x,k+1); //尝试下一位 
       // _____________________________________________ // 填空处
       {t=x[k]; x[k]=x[i]; x[i]=t;} //回溯,使i++时回到初始状态(恢复到下探之前的状态) 
    }  //递归 
}
    
int main()
{
    int x[] = {1,2,3,4,5,6,7,8,9};
    f(x,0);    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值