13年蓝桥杯 A组 c++真题
真题1:
思路:1.使用Excel时发现出生日期过于久远导致无法解析,Excel无法直接处理这些日期,因此需要将年份加上2000来进行计算
2.模拟日历翻转主要基于以下四个关键条件
- 31天的月份 碰到32 要进1 且如果月份为12 时要进1
- 30天的月份 碰到31 要进1
- 2月份 当是闰年时 碰到30要进1 不是闰年时,碰到29要进1
其中闰年的判断
if((y%4==0&&y%100!=0)||y%400==0)
有个技巧用题目给的数据进行验证
/*
题目标题: 高斯日记
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
请严格按照格式,通过浏览器提交答案。
注意:只提交这个日期,不要写其它附加内容,比如:说明性的文字。
1799-07-16*/
/* 1 3 5 7 8 10 12*/
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int check(int y){
if(y%4==0&&y%100!=0) return 1;
if(y%400==0) return 1;
return 0;
}
int main(){
int y=1777;
int m=4;
int d=30;
for(int i=1;i<8113;i++){
d++;
if(d==31&&(m==4||m==6||m==9||m==11)){d=1;m++; continue;}
if(d==32&&(m==1||m==3||m==5||m==7||m==8||m==10||m==12)){d=1;m++;
if(m==13) {y++;m=1;} continue;}
if(d==29&&!check(y)&&m==2){d=1;m++;continue;}
if(d==30&&check(y)&&m==2){d=1;m++;continue;}
}
printf("%d-%d-%d\n",y,m,d);
}

真题2:
题目:
题目标题: 排它平方数
小明正看着 203879 这个数字发呆。
原来,203879 * 203879 = 41566646641
这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。
具有这样特点的6位数还有一个,请你找出它!
再归纳一下筛选要求:
1. 6位正整数
2. 每个数位上的数字不同
3. 其平方数的每个数位不含原数字的任何组成数位

答案是一个6位的正整数。
建议您使用浏览器上交作业
思路采用枚举法。第一步是列举所有具有不同位数组合的六位数字串;接着计算这些数字的平方值,并检查所得结果是否包含了原始数字的所有字符。关键在于使用不等于符号(!=)来进行判断,并且主要利用模运算来验证字符是否存在。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
using namespace std;
int main(){
for(int i=1;i<=9;i++){
for(int j=0;j<=9;j++)
if(i!=j){
for(int k=0;k<=9;k++){
if(k!=i&&k!=j){
for(int l=0;l<=9;l++){
if(l!=k&&l!=i&&l!=j){
for(int m=0;m<=9;m++){
if(m!=i&&m!=j&&m!=k&&m!=l){
for(int n=0;n<=9;n++){
if(n!=i&&n!=j&&n!=k&&n!=l&&n!=m){
long long a=i*100000+j*10000+k*1000+l*100+m*10+n;
// cout<<a<<endl;
long long b=a*a;
int flag=1;
while(b){
int temp=b%10;
if(temp==i||temp==j||temp==k||temp==l||temp==m||temp==n) {
flag=0;
break;
}
b/=10;
}
if(flag==1)cout<<a<<endl;
}
}
}
}
}
}
}
}
}
}
return 0;
}

在第二种解法中存在一些需要注意的关键点。
就是利用stringstream将整数转换为字符串。
然后用字符串的find函数可以判断该整数是否存在于其中;::npos表示未找到。
/** * 检查xx中是否含有x中的数字
* @param x
* @param xx
* @return
*/
bool check(long long x,long long xx){
string str_x,str_xx;
i2s(x,str_x);
i2s(xx,str_xx);
for(int i=0;i<str_x.length();i++){
if(str_xx.find(str_x[i])!=string::npos)
return false;
}
return true;
}
void i2s(long long x,string &basic_string ){
stringstream ss;
ss<<x;
ss>>basic_string;
}

真题3:
题目:
标题: 振兴中华
小明参加学校的趣味运动会项目组,在其中一项活动中需要完成跳格子游戏。游戏场地地上画着多个格子区域,在每个格子里都写着一个汉字(也可参见p1.jpg)。
从"起"字出发依次跳跃,在横向或纵向移动到相邻的格子中继续前进的过程中必须依次经过"振"、"兴"、"中"等关键字方块区域,并最终到达标有"华"字的终点方块区域结束比赛。
比赛中规定参与者必须按照顺序准确地跳跃并刚好经过所有规定的关键字方块区域才能完成比赛任务。
请计算小明共有多少种不同的跳跃路线可选?
答案是一个整数,请通过浏览器直接提交该数字。
思路:
因为只要向右和向下走都构成
因为只要向右和向下走都构成
边缘
- 我们发现无需判断是否构成语句(因为它们都可以被使用)
- 我们需要明确枚举的总数量是多少
- 枚举的策略主要有递归法和迭代法(前者通过分治将复杂问题分解为更小的问题解决而后者则通过逐步遍历所有可能性实现目标)
- 在编写递归代码时, 核心在于将大问题分解为若干个小问题, 在这个问题中, 则表现为能够向下移动以及向右移动
- 因此, 在编写递归函数时需特别注意设置合理的终止条件(通常是在到达边界或无法进一步推进的情况下触发)
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int f(int x,int y){
if(x==3||y==4) return 1;
return f(x+1,y)+f(x,y+1);
}
int main(){
cout<<f(0,0)<<endl;
return 0;
}

真题4:
题目:
标题: 颠倒的价牌
小李的店里专卖其它店中下架的样品电视机,可称为:样品电视专卖店。
其标价都是4位数字(即千元不等)。
小李为了使标价清晰且便于阅读,在店铺中设置了成套预制的标价签,并采用外观与数字显示器相似的设计。这些标价签只需借助颜色笔将数字描绘在上面即可完成安装(参见p1.jpg)。
这种价牌具有独特的特性,在某些情况下正着放或倒着放都是有效的数值。例如1、2、5、6、8、9、0这些数字都可以正常使用。这样一来的话,则可能造成价格显示与实际不符。例如将'1958'倒置,则显示为'8561'时会相差几千元!
当然,多数情况不能倒读,比如,1110 就不能倒过来,因为0不能作为开始数字。
一天里发生了悲惨的事情。原本打算出售的两个电视机因为某个店员不小心被挂在墙上而被颠倒了位置,并且全部售出了!
值得庆幸的是,在本次交易中价格波动有限。其中一盏价牌出现了亏损约两百元的情况,另一盏却盈利约八百元。合计后发现净赚金额为五百五十八元。
请根据这些信息计算:赔钱的那个价牌正确的价格应该是多少?
答案是一个4位的整数,请通过浏览器直接提交这个数字
好像小题一般都是靠暴力枚举
好像小题一般都是靠暴力枚举
通常小问题都是通过暴力列举来解决
通常小问题都是通过暴力列举来解决
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int x1[100000];
int x2[100000];
int y1[100000];
int y2[100000];
//1 2 5 6 8 9 0
int tonum(int x){
switch(x){
case 1:return 1;
case 2:return 2;
case 5:return 5;
case 6:return 9;
case 8:return 8;
case 9:return 6;
case 0:return 0;
default: return 10000;
}
}
int main(){
int lenx=0;
int leny=0;
for(int i=1000;i<10000;i++){
if(i%10==0) continue;
int temp=i;
int sum=0;
while(temp){
sum*=10;
sum+=tonum(temp%10);
temp/=10;
}
if(i-sum>=200&&i-sum<300){x1[lenx]=i;x2[lenx++]=i-sum;}
if(sum-i>=800&&sum-i<900){y1[leny]=i;y2[leny++]=sum-i;}
}
for(int i=0;i<lenx;i++){
for(int j=0;j<leny;j++){
if(y2[j]-x2[i]==558){
cout<<x1[i]<<endl;
return 0;
}
}
}
return 0;
}

真题5:
