2013年蓝桥杯省赛全面解析系列&&题目思维拓展(AB组合并剖析 C++)

2013年蓝桥杯省赛全面解析系列&&题目思维拓展

一.2013年 C++ B组真题

A.高斯日记

1.题目描述

大数学家高斯有个好习惯:无论如何都要记日记。

他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210

后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?

高斯出生于:1777年4月30日。

在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。

高斯获得博士学位的那天日记上标着:8113

请你算出高斯获得博士学位的年月日。

提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21

请严格按照格式,通过浏览器提交答案。
注意:只提交这个日期,不要写其它附加内容,比如:说明性的文字。

2.提取信息

已知某一日期,问过多少天之后的日期是多少?

3.思路与分析

这道题直接可以模拟翻日历的过程,分别需要考虑每个月有不同的天数,以及平年闰年中二月份天数的不同。
不妨想像一下:
1.一天一天过去,每当到了月末一天就要进入下一个月。
2.一月一月过去,每当到了12月31日之后就要进入下一年。
3.如此循环往复,直到到达了指定的天数结束循环。

4.源代码

#include<iostream>
using namespace std;
bool LeapYear(int y){
   
	return (y%4==0&&y%100!=0)||(y%400==0);
}
int main(){
   
	int y=1777;
	int m=4;
	int d=30;
	for(int i=1;i<8113;++i){
   
		d++;
	    if(m==12&&d==32){
   
	    	y++;
	    	m=1;
	    	d=1;
	    	continue;
    	}
    	if((m==1||m==3||m==5||m==7||m==8||m==10)&&d==32){
   
	    	m++;
	    	d=1;
	    	continue;
	    }
    	if((m==4||m==6||m==9||m==11)&&d==31){
   
	    	m++;
		    d=1;
		    continue;
	    }
	    if(m==2&&LeapYear(y)&&d==30){
   
		    m++;
			d=1;
			continue;
		}
		if(m==2&&!LeapYear(y)&&d==29){
   
			m++;
			d=1;
			continue;
		}
    }
	cout<<y<<"-"<<m<<"-"<<d;
	return 0;
}

5.小结与拓展

本题主要考查对日期类的操作,当然用数组存日期也可以。对于日期类操作可以有许多种不同的题目,现就本小题进行拓展:
1.问几月几号是星期几?
有一个快速办法:假设星期为w,年份为y,月份为m,日期为d
则满足:
w = ( d + 2 m + 3 ( m + 1 ) / 5 + y + y / 4 − y / 100 + y / 400 ) % 7 w=(d+2m+3(m+1)/5+y+y/4-y/100+y/400)\%7 w=(d+2m+3(m+1)/5+y+y/4y/100+y/400)%7
之后再加一就是星期几了。
注意:1,2月要当成13,14月计算。

B.马虎的算式

1.题目描述

小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。

有一次,老师出的题目是:36 x 495 = ?

他却给抄成了:396 x 45 = ?

但结果却很戏剧性,他的答案竟然是对的!!

因为 36 * 495 = 396 * 45 = 17820

类似这样的巧合情况可能还有很多,比如:27 * 594 = 297 * 54

假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)

能满足形如: ab * cde = adb * ce 这样的算式一共有多少种呢?

请你利用计算机的优势寻找所有的可能,并回答不同算式的种类数。

满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。

答案直接通过浏览器提交。
注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。

2.提取信息

满足 a b + c d e = a d b + c e ab+cde=adb+ce ab+cde=adb+ce这样的算式一共有多少个?

3.思路与分析

用五重循环分别枚举a,b,c,d,e五个变量。

4.源代码

#include<iostream>
using namespace std;
int main(){
   
	int ans=0;
	for(int a=1;a<=9;++a){
   
		for(int b=1;b<=9;++b){
   
			if(a==b)  continue;
			else{
   
				for(int c=1;c<=9;++c){
   
					if((a==c)||(b==c))  continue;
					else{
   
						for(int d=1;d<=9;++d){
   
							if((a==d)||(b==d)||(c==d))  continue;
							else{
   
								for(int e=1;e<=9;++e){
   
									if(a==e||b==e||c==e||d==e)  continue;
									else{
   
										if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)){
   
											ans++;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	cout<<ans;
	return 0;
}

5.小结与拓展

本题暴力枚举就行了,没什么可拓展的。A组排他平方数也考了同样的枚举方法。

C.第39级台阶

1.题目描述

小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!

站在台阶前,他突然又想着一个问题:

如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?

请你利用计算机的优势,帮助小明寻找答案。

要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。

2.提取信息

一次上一个台阶或上两个台阶,且要求左脚起步右脚落地,问上到第39个台阶时有几种方法?

3.思路与分析

第一种做法:此题是典型的动态规划,也可以理解成fib数组的应用,因此使用递推法列写状态转移方程,其中开dp二维数组表示走到第i级台阶时走奇数或者偶数步数有几种走法。
d p [ 0 ] [ i ] = d p [ 1 ] [ i − 1 ] + d p [ 1 ] [ i − 2 ] dp[0][i]=dp[1][i-1]+dp[1][i-2] dp[0][i]=dp[1][i1]+dp[1][i2]
d p [ 1 ] [ i ] = d p [ 0 ] [ i − 1 ] + d p [ 0 ] [ i − 2 ] dp[1][i]=dp[0][i-1]+dp[0][i-2] dp[1][i]=dp[0][i1]+dp[0][i2]
上式表明在奇数或者偶数步数下走第i级台阶可以由第i-1级台阶和第i-2级台阶分别转移而来。

第二种做法:此题又可以用递归实现,利用dfs搜索状态,此状态可以设置两个参数:第一个参数是剩下的阶梯数,第二个参数是已走的步数。因此每递归一次已走的步数加1,同时往两个方向深搜:走一步和走两步。可以定义函数头:

void dfs(int stairs,int step)

4.源代码

1.动态规划(递推)

#include<iostream>
using namespace std;
int main(){
   
	int dp[2][105];
	dp[0][0]=1;
	dp[1][0]=0;
	dp[0][1]=1;
	dp[1][1]=1;
	for(int i=2;i<39;++i){
   
		dp[0][i]=dp[1][i-1]+dp[1][i-2];
		dp[1][i]=dp[0][i-1]+dp[0][i-2];
	}
	cout<<dp[1][38];
	return 0;
}

2.深搜(递归)

#include<iostream>
using namespace std;
int ans=0;
void dfs(int stairs,int step){
   
	if(stairs<0){
   
		return;
	}
	if(stairs==0&&step%2==0){
   
		ans++;
		return;
	}
	dfs(stairs-1,step+1);
	dfs(stairs-2,step+1);
}
int main(){
   
	dfs(39,0);
	cout<<ans;
	return 0;
}

5.小结与拓展

走楼梯这道题既可以用dp又可以dfs深搜。
可以说fib数组的热度非常高。现就本小题进行拓展:
每次可以走任意奇数个台阶,问n阶台阶有几种走法?
继续分析状态转移方程:
d p [ i ] = d p [ i − 1 ] + d p [ i − 3 ] + . . . + d p [ 1 ] dp[i]=dp[i-1]+dp[i-3]+...+dp[1] dp[i]=dp[i1]+dp[i3]+...+dp[1]
即这级台阶一定是由前面迈奇数个台阶转移而来。
核心代码如下:

for(int i=1;i<=n;++i){
   
    dp[i]=0;
    for(int j=i-1;j>=0;j-=2){
       //步数为2
        dp[i]+=dp[j];
    }
}

D.黄金连分数(这题还得想想)

1.题目描述

黄金分割数0.61803… 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。

对于某些精密工程,常数的精度很重要。也许你听说过哈勃太空望远镜,它首次升空后就发现了一处人工加工错误,对那样一个庞然大物,其实只是镜面加工时有比头发丝还细许多倍的一处错误而已,却使它成了“近视眼”!!

言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。

比较简单的一种是用连分数:
在这里插入图片描述

这个连分数计算的“层数”越多,它的值越接近黄金分割数。

请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。

小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)

你的任务是:写出精确到小数点后100位精度的黄金分割值。

注意:尾数的四舍五入! 尾数是0也要保留!

显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。

2.提取信息

输出黄金连分数精确100位的结果。

3.思路与分析

此题暂无思路(涉及到大数运算后续讨论)。

E.前缀判断

1.题目描述

如下的代码判断 needle_start指向的串是否为haystack_start指向的串的前缀,如不是,则返回NULL。

比如:“abcd1234” 就包含了 “abc” 为前缀

char* prefix(char* haystack_start, char* needle_start)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值