2013年蓝桥杯省赛C++B组真题与题解

1 高斯日记

题目:

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

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

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

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

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

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

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

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

题解:
已知5343是1791年12月15日,求8113对应日期,本题需要计算的数字较小,因此可以用Excel直接求解。如下图中,依次从1791年开始加每年的数字,A栏是年份,B栏是该年天数,C栏是从5343开始依次加上该年天数后的数字,如C2栏即为5343加上1791年剩余的16天后的数字,C3栏即为加完1792年整年366天后的数字,E栏为当年年份除以4后得到的数字,若为整数且该年年数不是100的整数则该年为闰年,按366天算。 在这里插入图片描述

发现8113在1798年和1799年之间,可得8113减去7916为197,依次减去每月天数,如下,在这里插入图片描述

可知减完6月份时还剩16天,可得出所求日期为1799-07-16

2 马虎的算式

题目:

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

有一次,老师出的题目是: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 这样的算式一共有多少种呢?

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

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

题解:
找出满足ab * cde = adb * ce算式的答案个数,a b c d e是代表1~9不同的5个数字。只要满足该算式即计为不同种类,所以不存在重合问题,一共只有5种数字,可以直接暴力计算。只需要注意判断每个数字都不相同和判断算式的满足。代码如下:在这里插入图片描述

3 第39级台阶

题目:

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

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

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

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

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

题解:
一共39级台阶,每一步上1级或2级台阶,也就是每上一次台阶,选择上1级或2级,剩下的台阶再选择上1级或2级,逐步递推,直到走完39级台阶,中间加上步数这个参数,最后判断步数是不是偶数,是的话就算进答案个数里。代码如下:在这里插入图片描述

4 黄金连分数

题目:

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

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

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

比较简单的一种是用连分数:

              1
黄金数 = ---------------------
                    1
         1 + -----------------
                      1
             1 + -------------
                        1
                 1 + ---------
                      1 + ...

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

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

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

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

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

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

题解:
求黄金分割数,由连分数的层级可联想到递归,但单纯的递归无法求精确到小数点后100位的黄金分割数,若用连分数求,按层级依次为1,1/2,2/3,3/5,5/8,…….由此可想到斐波那契数列,又称黄金分割数列,为1、1、2、3、5、8、13、21、34……此数列从第3项开始,每一项都等于前两项之和,而此题最终要求的小数点后100位精度即为斐波那契数列中某两项相除得到的值,因此该题转化为求斐波那契数列的某两项的商精确到小数点后100位。因为涉及到的数字过大所以不能用已经规定的数据类型定义,我选择用C++中的vector类型储存需要得到的两项数字和最终答案即小数点后100位数字。前面的定义如下: 在这里插入图片描述

至于n为什么是300,后面会有解释。
首先是主函数,因为已知前两项是1,所以直接先push进A和B,接下来就是不断的求和,清空,和替换A和B的数据,保证A始终小于B,这里使用的高精度加法模板add()之前发过解析,就不过多解释。 在这里插入图片描述

这样就求出了斐波那契数列中我们需要的那两项数字了,接下来就是求A和B相除的结果,这里需要将除法转换成减法,其原理如下:比如要求1/3,将1后面添个0,得到10,用10去减3,一共可以减3次,这个减的次数就是小数点后的第一位,减完余1,再在这个1后面添个0,继续去减3,这次减的次数就是小数点后的第二位了,以此类推,想要得到小数点后100位至少得完成100次这样的操作,主函数实现如下:(高精度减法sub函数和判断A和B大小cmp的解析同上,若需详细解析,可看基础算法-高精度的加、减、乘、除运算-C++实现在这里插入图片描述

最后按照小数的格式输出,这里要注意,虽然只需要求小数点后100位,但不能只把n设置为101,还要加大n的值多试几次,直到求出的小数点后100位的值稳定了才是最终答案,且要求到101位再四舍五入。
比如,n=101时,小数点后101位:0.61803398874989484820458683436563811772030898118204323171968168093976058120430545788325825154507567808
n=200时,小数点后101位:0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970803605876859146255
n=300时,小数点后101位:0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748
n=400时,小数点后101位:0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748
可以看到直到n=300的时候小数点后100位数字才稳定,此时得到的才是正确答案,再四舍五入下,就得到最终答案了,全部代码如下:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

vector<int> A, B, C, ans;
int n = 300;

bool cmp(vector<int> &A, vector<int> &B)//比较A与B大小
{
   
    if (A.size() != B.size()) return A.size() > B.size();
    for (int i = A.size() - 1; i >= 0; i --)
        if (A[i] != B[i]) return A[i] > B[i];
    return true;
}

vector<int> add(vector<int> &A, vector<int> &B)//高精度加法
{
   
    if (A.size() < B.size()) return add(B, A);
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++)
    {
   
        t += A[i];
        if (i 
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值