问题
【问题描述】
在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。
牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月份,最后2位代表日期。显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。
牛牛认为,一个日期是回文的,当且仅当表示这个日期的8位数字是回文的。现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。
【输入】
输入包括两行,每行包括一个8位数字。
第一行表示牛牛指定的起始日期date1,第二行表示牛牛指定的终止日期date2。保证date1和date2都是真实存在的日期,且年份部分一定为4位数字,且首位数字不为0。保证date1一定不晚于date2。
【输出】
输出一行,包含一个整数,表示在date1和date2之间,有多少个日期是回文的。
【输入样例】
20110101 |
---|
20111231 |
【输出样例】
1
思路分析
对于回文问题,我最初的思路是将数字以string类存储,然后将串翻转,检查这两串是否相等并且这两串是否满足各种限定条件,然后就被这种思路所困,遇到各种问题:年月日要先转成数字再来判断,以及如何将串向后移动。。。。。
然后知道这种思路行不通了,只能去查看他人代码,发现了他们的思路——
直接对年份进行枚举,同一年不可能存在两个回文日期,以此枚举年份,构造该年份的回文日期,然后检查该构造出的回文日期是否满足各个条件,以此解决问题。
回文是一种很巧妙的结构,所以以后如果遇到类似回文的题目可以考虑构造一部分然后再来进行判断。
代码
#include<iostream>
#include<algorithm>
using namespace std;
int month1[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//月份的数组
int ans;
bool check(int x){//检查date是否满足条件
int year=x/10000,month=(x%10000)/100,day=x%100;
if(!month&&month>12) return 0;//月份不满足条件
else if(month!=2&&day>month1[month]) return 0;//不为2的月份天数不满足条件
if(((year%4==0&&year%100!=0)||year%400==0)&&day>29) return 0;//为2的月份判断天数
else if(day>28) return 0;
return 1;//均符合
}
int main(){
int date1,date2;
cin>>date1>>date2;
for(int i=date1/10000;i<=date2/10000;i++){//枚举年份
int date=i,x=date;
while(x){
date=date*10+x%10;//将date构造成8位
x/=10;
}
if(date>=date1&&date<=date2&&check(date)) ans++;//如果date在两日期之间并且符合条件,数量加一
}
cout<<ans;
return 0;
}
(这是我写的第一篇博客,也是我为蓝桥杯所开始做的准备,现在我还是一个算法菜鸟,但是希望通过做不同的,不会的题,来丰富自己的思路与见识,加油吧,少年)