2013年蓝桥杯省赛真题解析(上)(C/C++大学B组)

2013年蓝桥杯省赛真题解析(上)

(C/C++大学B组)

高斯日记:

#include<iostream>
using namespace std;
bool isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0)||(year % 400 == 0);
}
#define _for(i, x, y) for(int i = x;i < y;i++)
int main(){
    int year = 1777;
    int month = 4;
    int day = 30;
    const int mon_arr[] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};
    const int days = 8113 - 1;
    _for(i,0,days){
        //根据当前月份判断当前月的天数
        day++;
        if(month == 2 && day >= 29){
            if(isLeapYear(year))
                if(day == 30) {
                    month = 3;
                    day = 1;
                }
            if(!isLeapYear(year))
                if(day == 29)
                {
                    month = 3;
                    day = 1;
                }
            continue;
        }
        if(day == mon_arr[month] + 1){
            day = 1;
            if(month == 12) {
                year += 1;
                month = 1;
            } else
                month++;
        }
    }
    cout<<year<<" "<<month<<" "<<day<<endl;
    return 0;
}

马虎的算式:

#include<iostream>
#include<set>
using namespace std;
#define _for(i,start,end) for(int i = start;i <= end;i++)
int main(){
    //abcde
    //ab * cde = adb * ce
    int temp1,temp2,count = 0;
    set<int> Set;
    _for(a,1,9)
        _for(b,1,9)
            _for(c,1,9)
                _for(d,1,9)
                    _for(e,1,9){
        		//set写起来简单,但是显然,如果a = b,后面的c,d,e就不用跑了
        //这样写效率低下,在本地自己玩可以,若要提交代码的话,性价比不高。
                        Set.insert(a);
                        Set.insert(b);
                        Set.insert(c);
                        Set.insert(d);
                        Set.insert(e);
                        if(Set.size() < 5){
                            Set.clear();
                            continue;
                        }
                        temp1 = (a*10+b)*(c*100+d*10+e);
                        temp2 = (a*100+d*10+b)*(c*10+e);
                        if(temp1 == temp2)
                            count++;
                        Set.clear();
                    }
    cout<<count;
    return 0;
}
#include<iostream>
using namespace std;
#define _for(i,start,end) for(int i = start;i <= end;i++)
int main() {
    //abcde
    //ab * cde = adb * ce
    int temp1, temp2, count = 0;
    _for(a, 1, 9)_for(b, 1, 9) {
            if (b != a)
                _for(c, 1, 9) {
                    if (c != a && c != b)
                        _for(d, 1, 9) {
                            if (d != a && d != b && d != c)
                                _for(e, 1, 9) {
                                    if (e != a && e != b && e != c && e != d) {
                                        temp1 = (a * 10 + b) * (c * 100 + d * 10 + e);
                                        temp2 = (a * 100 + d * 10 + b) * (c * 10 + e);
                                        if (temp1 == temp2)
                                            count++;
                                    }
                                }
                        }
                }
        }
    cout<<count;
    return 0;
}

第39阶台阶:

#include<iostream>
using namespace std;
int walk(int left,int count){
	int sum = 0;
    if(left - 1 >= 0)
        sum += walk(left - 1,count + 1);
    if(left - 2 >= 0)
    	sum += walk(left - 2,count + 1);
    if(left == 0)//保证是偶数级台阶
		if(count % 2 == 0)
			return 1;
		else
			return 0;
	return sum;
}
int main() {
    int count = 0;
    cout<<walk(39,count);
    return 0;
}

注意:

此题为填空题,暴力递归出答案即可。(一个填空题要什么自行车)若考虑记忆背包,则必须想清楚在k这个台阶存2个值,一个是走奇数步的值,一个是走偶数步的值。比如在台阶为0时(就是left=0的时候),奇数步返回0,偶数步返回1。

黄金连分数:

  1. 转为求斐波拉契的n和n+1项
  2. n取多少?再增加n,小数点后101位没有变化
  3. 不能用c语言所定义的整数型直接运算,而要手工地写大数加法和除法(减法)

注:可以用java的大整数库算出答案(比赛能不能背地里用java这就不知道了)

这一题包含了高精度加法、减法、除法。

不是很完善但是指出了大致的思路。

适合用作学习string类的材料

#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string add(string a,string b){
    /**
     高精度加法模板,
     在处理a,b谁长度长的问题上。string ans(len,'0'),再把a拷贝进ans。
     我们不用a[i] + b[i]而是用ans[i] + b[i],这样避免a的长度小而导致下标越界。
     这样的话,如果b的长度最长也不影响,因为ans后面用'0'填充了。
     我们遍历len = max(lenA,lenB)
     如果a是最长的,那么当超过b的长度时,我们只加ans[i]
     */
     //去除开头的0,"000123" -> "123"
     a = a.substr(a.find_first_not_of('0'));
     b = b.substr(a.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长,全部字符为0
     //把a拷贝到ans中
     for(int i = 0;i < lenA; i++){
         ans[i] = a[i];
     }
     int tmp = 0;
     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;//tmp是上一位相加后的进位
     }
     reverse(ans.begin(),ans.end());

    return ans.substr(ans.find_first_not_of('0'));
}
int cmp(string a,string b){
    //防止a全部是0
    //unsigned long i1 = a.find_first_not_of('0');
    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;
        //a == b
        else return 0;
    }
}
string subtract(string a,string b){
    //此函数中a必须大于b
    //完整的减法,a可以小于b,结果为负数,交换a,b进行下面的代码
    //1.翻转
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    //2.按位做减法
    //for(int i = 0;i < b.length(); i++)里面的i++是否和++i等价
    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
            //my
            a[i+k] = a[i+k] - '1'+'0';
            a[i] = (a[i] - '0' + 10) -(b[i] - '0') + '0';
        }
    }
    reverse(a.begin(),a.end());
    //使用a.find_first_not_of('0'),要注意若a==b的话,ans = "0";那么找不到非0,那么会越界
    //预防一下,就是预防特殊的a == b;
    if(a.find_first_not_of('0') == string::npos)return "0";
    return a.substr(a.find_first_not_of('0'));
}
void i2s(int t,string &str){
    int len_t = 0;
    string temp = "0";
    if(t == 0)
        str.append(temp);
    while(t){
        temp = t%10 + '0';
        str.append(temp);
        t /= 10;
        len_t++;
    }
    reverse(str.begin(),str.end());
}
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 = subtract(a,b);//不同做减法
            t++;//记录减法做了多少次
        }
        string t_str;
        //我先把i2s注释掉
        i2s(t,t_str);
        ans.append(t_str);
    }
    return ans;
}
int main() {
    string a = "1";
    string b = "1";
    for(int i = 3;i <= 500;i++){
        string tmp = b;
        b = add(a,b);
        a = tmp;
    }
    string ans = divide(a,b);
    cout<<ans<<endl;
    cout<<ans.length() - 2<<endl;
    //拿到答案之后,记得手动4舍5入
    return 0;
}

前缀判断:

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

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

#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
/**
 *
 * @param haystack_start 母串
 * @param needle_start 前缀
 * @return
 */
char* prefix(char* haystack_start,char* needle_start){
    //needle_start是否为haystack_start的前缀
    char* haystack = haystack_start;
    char* needle = needle_start;
    while(*haystack && *needle) {
        //当2个指针都没越界,且二个指针指向的内容都不相等,指针后移
        if (*(haystack++) != *(needle++)) {
            return NULL;
        }
    }
    //假设有一个字符串长度短,就发生指针越界,出循环
    //if(*needle)说明这个时候needle的指针没有越界,那么就说明haystack比needle要短,
    //所以needle_start不是haystack的前缀,返回NULL
    if(*needle)
        return NULL;
    //if(*needle)为假,说明needle比haystack短。在while循环可以看出,
    // needle的字符和haystack_start前面的字符相等,说明needle是haystack的前缀。
    return haystack_start;
}

int main() {
    char a[] = "abcd1234";
    char b[] = "abc";
    cout<<prefix(a,b);
    //或prefix("abcd1234","abc");
    return 0;
}
发布了22 篇原创文章 · 获赞 0 · 访问量 788

猜你喜欢

转载自blog.csdn.net/sjxgghg/article/details/105394620
今日推荐