洛谷 P2010 回文日期 题解

P2010 回文日期

题目描述

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用88位数字表示一个日期,其中,前44位代表年份,接下来22位代表月 份,最后22位代表日期。显然:一个日期只有一种表示方法,而两个不同的日期的表 示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的8位数字是回文的。现 在,牛牛想知道:在他指定的两个日期之间包含这两个日期本身),有多少个真实存 在的日期是回文的。

一个88位数字是回文的,当且仅当对于所有的i ( 1 le i le 8)i(1≤i≤8)从左向右数的第i个 数字和第9-i9−i个数字(即从右向左数的第ii个数字)是相同的。

例如:

•对于2016年11月19日,用88位数字2016111920161119表示,它不是回文的。

•对于2010年1月2日,用88位数字2010010220100102表示,它是回文的。

•对于2010年10月2日,用88位数字2010100220101002表示,它不是回文的。

每一年中都有1212个月份:

其中,1,3,5,7,8,10,121,3,5,7,8,10,12月每个月有3131天;4,6,9,114,6,9,11月每个月有3030天;而对于22月,闰年时有2929天,平年时有2828天。

一个年份是闰年当且仅当它满足下列两种情况其中的一种:

1.这个年份是44的整数倍,但不是100100的整数倍;

2.这个年份是400400的整数倍。

例如:

•以下几个年份都是闰年:2000,2012,20162000,2012,2016。

•以下几个年份是平年:1900,2011,20141900,2011,2014。

输入格式

两行,每行包括一个88位数字。

第一行表示牛牛指定的起始日期。

第二行表示牛牛指定的终止日期。

保证date_idate_i和都是真实存在的日期,且年份部分一定为44位数字,且首位数字不为00。

保证date 1date1 —定不晚于date 2date2。

输出格式

一个整数,表示在date1date1和date2date2之间,有多少个日期是回文的。

输入输出样例

输入 #1

20110101
20111231

输出 #1

1

输入 #2

20000101
20101231

输出 #2

2

说明/提示

【样例说明】

对于样例1,符合条件的日期是 2011110220111102。

对于样例2,符合条件的日期是 2001100220011002 和 2010010220100102 。

【子任务】

对于 60% 的数据,满足 date1 = date2date1=date2。

【思路】

模拟
难度还是很一般的模拟题目
首先,先说一下闰年这个玄学的东西,为什么要说闰年呢
因为闰年的2月有二十久天,这好像谁都知道吧
因为这个第29天的出现,导致可能会出现一个回文数,这个时候大家可能就会考虑了
每一年都判断一下是不是闰年,如果是那2月就有29天,如果不是那就有28天
其实根本不需要考虑这么复杂,如果出现这种原因可能是你还没再考虑一下的缘故
2月29构成的是0229,能和他组成回文的年份只有9220年,同时这一年也是闰年,所以这就很显然了
根本不需要管是不是闰年,每年都按照2月有29天来枚举,反正除了9220年都不会和2月29组成回文

最难搞的地方说完了
再说一下次难搞的地方

怎么判断是不是回文呢?
我的思路是这样的,在输入的时候实现吧字符串预处理为nian,yue,ri这三个变量分别储存年月日
然后枚举到每一天的时候,将ri的个位和十位换一下位置比如29号吧,就变为92,注意这里还是以数字的形式
然后同理,也将yue的各位和十位转换一下位置,加起来两个转换过后的数
如果这个数等于年,那么就是回文数
不等于就不是回文数,原理很简单我就不多赘述了

好了,两大稍微有点难度的东西解决掉了,剩下的小细节小骨头我就在代码里面标注了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
string s1,s2;
int x,y,z;
int nian,yue,ri;
int js = 0;
int month[13] = {0,31,29,31,30,31,30,31,31,30,31,30,31};//预处理出每一个月份里面的额天数 

bool acioi()//判断是否是回文的函数 
{
	int qwq = (ri % 10) * 10 + ri / 10;
	int owo = (yue % 10) * 10 + yue / 10;
	int awa = owo + qwq * 100;
	if(nian == awa)
		return true;
	else
		return false;
}

int main()
{
	cin >> s1;//输入起始 
	nian = (s1[0] - '0') * 1000 + (s1[1] - '0') * 100 + (s1[2] - '0') * 10 + (s1[3] - '0');
	yue = (s1[4] - '0') * 10 + (s1[5] - '0');
	ri = (s1[6] - '0') * 10 + (s1[7] - '0');//处理出来 
	cin >> s2;//输入结尾 
	x = (s2[0] - '0') * 1000 + (s2[1] - '0') * 100 + (s2[2] - '0') * 10 + (s2[3] - '0');
	y = (s2[4] - '0') * 10 + (s2[5] - '0');
	z = (s2[6] - '0') * 10 + (s2[7] - '0');//处理出来 
	while(nian != x || yue != y || ri != z)//没到结尾那一天就不结束 
	{
		if(acioi() == true)//判断一下是否是闰年 
			js ++;//计数器累加 
		ri ++;//下一天 
		if(ri == month[yue] + 1)//这个月过完了 
		{
			ri = 1;//下一个月的第一天 
			yue ++;//下一个月了 
			if(yue == 13)//今年过完了 
			{
				nian ++;//下一年了 
				yue = 1;//下一年的第一个月 
			}
		}
	}
	//从上面可以看出,最后一天也就是输入s2这一天是没有没枚举到的,所以这里在acioi一次就可以了 
	if(acioi() == true)
		js ++; 
	cout << js << endl;//输出计数器 
}
原文地址:https://www.cnblogs.com/acioi/p/11605875.html