前言
唤我沈七就好啦。
日期类问题可以说是蓝桥杯当中的常客了,
我整理了一下历年真题,归纳出了其中的模板。
希望对你有所帮助。
制造日期回文数
#include<bits/stdc++.h> using namespace std; int sum; int m[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};//枚举月份 int main() { int a,b,x; cin>>a>>b; for (int i = 1; i <13; i ++ )//月 for(int j=1;j<=m[i];j++)//日 { //月份和日期确定下来之后,回文日期的年份也就确定下来了 x=(j%10*1000+j/10*100+i%10*10+i/10)*10000+i*100+j; if(x>=a&&x<=b)//判断是否在给定区间内 sum++; } cout<<sum; return 0; }
判断日期是否合法
int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool check(int y ,int m , int d) { if(!d||!m||m>12)return 0; if(m!=2) { if(d>day[m]) return 0; } else { int idx=((y % 100!=0 && y % 4==0)||(y%400==0)); if(d>day[2]+idx)return 0; } return 1; }
判断某年月份的天数
int moth[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int get(int y, int m) { int leap = y%4==0&&y%100!=0||y%400==0; if(m!=2) return moth[m]; return 28+leap; }
计算某两天的相隔天数
代码做法
#include<bits/stdc++.h> using namespace std; int moth[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int get(int y, int m) { int leap = y%4==0&&y%100!=0||y%400==0; if(m!=2) return moth[m]; return 28+leap; } int main() { int ans=0; int y,m,d; int y1,m1,d1; cin>>y>>m>>d; cin>>y1>>m1>>d1; while(1) { ans++,d++; if(d>get(y,m)) m++,d=1; if(m>12) y++,m=1; if(y==y1&&m==m1&&d==d1) { cout<<ans; return 0; } } return 0; }
计算器妙用
某两天内星期一的个数
代码做法
1.先计算出两日期的相隔天数
2.由当天的日期星期反推给定日期的星期
(day 1 = day 2 - 相隔天数 % 7 )
3.根据给定日期的星期与所取星期的关系,判断答案与 相隔天数 / 7 是否差 1
Excel妙用
注:Excel 只能计算1900年后的时间
给定年月日求n天后对应的日期
#include<bits/stdc++.h> using namespace std; int moth[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int get(int y, int m) { int leap = y%4==0&&y%100!=0||y%400==0; if(m!=2) return moth[m]; return 28+leap; } int main() { int y,m,d,n; cin>>y>>m>>d>>n; while(n--) { d++; if(d>get(y,m)) m++,d=1; if(m>12) y++,m=1; } printf("%d年%d月%d日",y,m,d); return 0; }
历年真题
高斯日记
第四届蓝桥杯C++组
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
坑点:
这题不能用Excel,不符合适用范围
根据上面模板算出时间后需要 - 1!!!
这计算的是相隔的天数 需要减去 1777年4月30日,他出生的那一天!!
#include<bits/stdc++.h> using namespace std; int moth[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int get(int y, int m) { int leap = y%4==0&&y%100!=0||y%400==0; if(m!=2) return moth[m]; return 28+leap; } int main() { int y,m,d,n; cin>>y>>m>>d>>n; while(n--) { d++; if(d>get(y,m)) m++,d=1; if(m>12) y++,m=1; } printf("%d年%d月%d日",y,m,d-1); //一定要 - 1!!!,因为这计算出来的是相隔的天数 需要减去 1777年4月30日,他出生的那一天!! return 0; }
日期问题
第八届蓝桥杯省赛C++组
小明正在整理一批历史文献。这些历史文献中出现了很多日期。
小明知道这些日期都在1960年1月1日至2059年12月31日。
令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
【 输入格式】
一个日期,格式是”AA/BB/CC”。
即每个’/’隔开的部分由两个 0-9 之间的数字(不一定相同)组成。
【输出格式】
输出若干个不相同的日期,每个日期一行,格式是”yyyy-MM-dd”。
多个日期按从早到晚排列。
【 数据范围】
0≤A,B,C≤9
【输入样例】:
02/03/04
【输出样例】:
2002-03-04 2004-02-03 2004-03-02
#include<bits/stdc++.h> using namespace std; int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool check(int y ,int m , int d) { if(!d||!m||m>12)return 0; if(m!=2) { if(d>day[m])return 0; } else { int idx=((y % 100!=0 && y % 4==0)||(y%400==0)); if(d>day[2]+idx)return 0; } return 1; } int main() { int a,b,c; scanf("%d/%d/%d",&a,&b,&c); for(int i = 19600101 ; i <= 20591231 ; i ++) { int y=i/10000,m=i%1000/100,d=i%100; if(check(y,m,d)) { if((y%100==a&&m==b&&d==c)|| //年月日 (y%100==c&&m==a&&d==b)|| // (y%100==c&&m==b&&d==a)) printf("%d-%02d-%02d\n",y,m,d);//补前导 } } return 0; }
黑色星期五
第一届蓝桥杯C/C++组
13号又是一个星期五。13号在星期五比在其他日子少吗?为了回答这个问题,请你写一个程序计算每个月的十三号落在周一到周日的次数。
给出N年的一个周期,要求计算1900年1月1日至1900+N-1年12月31日中十三号落在周一到周日的次数,N为正整数且不大于400。
这里有一些你要知道的:
1、1900年1月1日是星期一。
2、4,6,11和9月有30天。其他月份除了2月都有31天。闰年2月有29天,平年2月有28天。
3、年份可以被4整除的为闰年(1992年是闰年,但是1990年不是闰年)。
4、以上规则不适合于世纪年。可以被400整除的世纪年为闰年,否则为平年。所以,1700,1800,1900和2100年是平年,而2000年是闰年。
【输入格式】
一个正整数:N。
【输出格式】
七个在一行且相分开的整数,它们代表13日是星期六、星期日、星期一、…、星期五的次数。
【输入样例】
20
【输出样例】
36 33 34 33 35 35 34
#include<bits/stdc++.h> using namespace std; long long ans=1,cnt[100]; int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int get(int y,int m) { if(m!=2) return moth[m]; int leap=y%4==0&&y%100!=0||y%400==0; return 28+leap; } int main() { int n; cin>>n;n=n+1900-1; int y=1900,m=1,d=1; while(1) { d++; ans++; int day = ans%7; if(d>get(y,m)) m++,d=1; if(m>12) y++,m=1; if(d==13) cnt[day]++; if(y==n&&m==12&&d==31) { break; } } cout<<cnt[6]<<" "<<cnt[0]<<" ";//注意输出顺序,这是个坑 for(int i = 1 ; i <= 5 ; i ++) cout<<cnt[i]<<" "; return 0; }
完结散花
ok以上就是对 蓝桥杯日期类模板 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。
参考文献
https://www.acwing.com/activity/content/19/
https://blog.csdn.net/xiao_cangtian/article/details