蓝桥杯——2013第四届C/C++真题[省赛][B组](一)

简介: 蓝桥杯——2013第四届C/C++真题[省赛][B组]

1. 高斯日记(结果填空)


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

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


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


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

 

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


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


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


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


请严格按照格式,通过浏览器提交答案。

注意:只提交这个日期,不要写其它附加内容,比如:说明性的文字。

思路:很常规,用excel,和电脑自带的计算器都可以算,我这里就不演示了,我提供一下代码,得到的结果要减去1。

#include<iostream>
using namespace std;
class Date {
public:
    Date(int year, int month,int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    int GetMonthDay(int year, int month)
    {
        int Month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
        int day = Month[month];
        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
        {
            day += 1;
        }
        return day;
    }
    Date& operator+=(int day)
    {
        _day += day;
        while(_day > GetMonthDay(_year, _month))
        {
            _day -= GetMonthDay(_year, _month);
            _month++;
            if (_month == 13)
            {
                _year++;
                _month = 1;
            }
        }
        return *this;
    }
    void print()
    {
        cout << _year << "-" << _month << "-" << _day;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1(1777, 4, 30);
    d1 += 8113;
    d1.print();
  return 0;
}

答案:1799-7-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 这样的算式一共有多少种呢?


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

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


答案直接通过浏览器提交。

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

思路:我认为这道题是本届最简单的了,直接枚举,需要主要各个数字不相同就可以

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

答案:142

3. 第39级台阶(结果填空)


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

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

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

输出格式:

输出一个整数

思路: 读到这个题不知道有没有小伙伴跟我想法一样,把偶数步这个条件去掉不就是递归斐波那契数列嘛,这都练的熟透了,f(n-1)+f(n-2),那么这道题也就是说只要添加一个判断条件是否等于偶数步不就可以了嘛。

#include<iostream>
using namespace std;
int ants;
int f(int n,int step)
{
    if (n < 0)
    {
        return 0;
    }
    if (n==0||n==1)
    {
        if(step%2==0)
        ants++;
        return 0;
    }
    return f(n - 1,step+1) + f(n - 2,step+1);
}
int main()
{
    f(39,0);
    cout << ants << endl;
    return 0;
}

答案:51167078

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,不能忽略)

思路:简单的说一下这道题,运算量很大,代码量也很多,如果要是熟悉java中的BigDecimal还是很好做的,单纯用c++做这道题我认为性价比很低,所以考场上不要死磕一个题.好了,话不多说下面我带大家一起分析下本题.

image.png

/*1.转为求斐波那契数列的n和n+1项
2.n取多少?再增加n,小数点后的101位没有变化
3.不能用c语言中的整形直接运算,而要手工地写大数加法和除法*/
#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
using namespace std;
int n = 400;
void i2s(int num, string& str)
{
    stringstream ss;
    ss << num;
    ss >> str;
}
int cmp(string a, string b)
{
    if (a.find_first_not_of('0') == string::npos) a = '0';
    else a.substr(a.find_first_not_of('0'));
    if (b.find_first_not_of('0') == string::npos) b = '0';
    else b.substr(b.find_first_not_of('0'));
    if (a.length() > b.length())return 1;
    else if (a.length() < b.length())return -1;
    else {//长度相等
        if (a < b) return -1;
        if (a > b) return 1;
        else  return 0;
    }
}
string add(string a, string b)
{
    a = a.substr(a.find_first_not_of('0'));
    b = b.substr(b.find_first_not_of('0'));
    long long lenA = a.length();
    long long lenB = b.length();
    long long len = max(lenA, lenB) + 10;
    //翻转,便于从地位逐步求和
    reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
    string ans(len, '0');//初始化答案为len长,
    //把a拷贝到ans中
    for (int i = 0; i < lenA; i++)
    {
        ans[i] = a[i];
    }
    int tmp = 0;//tmp是上一位相加后的进位
    for (int i = 0; i < len; i++)
    {
        if (i < b.length())
            tmp += (ans[i] - '0') + (b[i] - '0');
        else
            tmp += (ans[i] - '0');
        ans[i] = tmp % 10 + '0';
        tmp /= 10;
    }
    reverse(ans.begin(), ans.end());
    return ans.substr(ans.find_first_not_of('0'));
}
//此处,a一定大于等于b
string substract(string a, string b)
{//完整的减法里面,a可以小于b,这时结果为负数,交换ab进行下面的代码
//1.翻转
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    //2.按位做减法
    for (int i = 0; i < b.length(); i++)
    {
        if (a[i] >= b[i])
        {
            a[i] = a[i] - b[i] + '0';
        }
        else {//就要借
            int k = 1;
            while (a[i + k] == '0')
            {
                a[i + k] = '9';
                k++;
            }
            //这里可以保证i+k这一位上不是0
            a[i + k] = a[i + k] - '1' + '0';
            a[i] = a[i] - '0' + 10 - (b[i] - '0') + '0';
        }
    }
    reverse(a.begin(), a.end());
    if (a.find_first_not_of('0') == string::npos) return "0";
    return  a.substr(a.find_first_not_of('0'));
}
string divide(string a, string b)
{
    //只考虑a<b的情况
    string ans = "0.";
    //转化成减法
    for (int i = 0; i < 101; i++)
    {
        a.append("0");
        int t = 0;
        while (cmp(a, b) >= 0)//a>b,不停做减法
        {
            a = substract(a, b);
            t++;//记录减法做了多少次
        }
        string t_str;
        i2s(t, t_str);
        ans.append(t_str);
    }
    return ans;
}
int main()
{
    string a = "1";
    string b = "1";
    for (int i = 3; i <= n; i++)
    {
        string tmp = b;
        b = add(a, b);
        a = tmp;
    }
    //a b是斐波那契的n-1和n项
    string ans = divide(a, b);
    cout << ans << endl;
    return 0;
}

这个就是C++的解法,很长,可以做为参考,下面我写下java的

package java_2013_B;
import java.math.BigDecimal;
public class Main004_黄金连分数 {
    public static void main(String[] args) {
        BigDecimal ans1 = fb(200).divide(fb(201),110,BigDecimal.ROUND_HALF_DOWN);
        BigDecimal ans2 = fb(300).divide(fb(301),110,BigDecimal.ROUND_HALF_DOWN);
        BigDecimal ans3 = fb(400).divide(fb(401),110,BigDecimal.ROUND_HALF_DOWN);
        BigDecimal ans4 = fb(800).divide(fb(801),110,BigDecimal.ROUND_HALF_DOWN);
        System.out.println(ans1.toPlainString().substring(0,103));
        System.out.println(ans2.toPlainString().substring(0,103));
        System.out.println(ans3.toPlainString().substring(0,103));
        System.out.println(ans4.toPlainString().substring(0,103));
    }
    static BigDecimal fb(int n){
        BigDecimal a = BigDecimal.ONE;
        BigDecimal b = BigDecimal.ONE;
        for (int i = 0; i < n; i++) {
            BigDecimal t = b;
            b = a.add(b);
            a=t;
        }
        return b;
    }
}

答案:0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748

5. 前缀判断(代码填空)


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


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

char* prefix(char* haystack_start, char* needle_start)
{
char* haystack = haystack_start;
char* needle = needle_start;
while(*haystack && *needle){
if(______________________________) return NULL;  //填空位置
}
if(*needle) return NULL;
return haystack_start;
}

思路:代码填空题,首先把代码复制到编译器中,注释掉需要填空的地方,然后看看结果是什么,这道题

image.png

没啥价值,下面开始分析代码,这个字符串匹配应该是司空见惯了,(*haystack&&*needle)这个语句判断两个指针都没有越界,那么while循环里应该就是挨个判断字符串是否相等.很容易写出*(haystack++)!=*(needle++);我们也可以写个主程序进行验证是否正确.

image.png

答案: *(haystack++)!=*(needle++)


相关文章
|
1月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
1月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
1月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
1月前
|
机器学习/深度学习 算法 关系型数据库
第十五届蓝桥杯C++B组省赛
第十五届蓝桥杯C++B组省赛
71 14
|
1月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
34 5
|
6月前
|
算法 测试技术 C++
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
|
6月前
|
数据安全/隐私保护 C++
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题
|
6月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
107 0
|
6月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
82 0
|
6月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
83 0