题目描述
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
输入描述
输入包含一个八位整数 N,表示日期。
对于所有评测用例,10000101 \le N \le 89991231,保证 N 是一个合法日期的 8 位数表示。
输出描述
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
输入输出样例
示例
输入
20200202
输出
20211202
21211212
运行限制
最大运行时间:1s
最大运行内存: 256M
精炼题目:有一种yyyymmdd格式的日期满足回文数,也就是后四位数字是前四位数字的倒置,还有一种yyyymmdd日期满足回文日期的同时又满足ABABBABA型,称为ABABBABA型回文日期,现在给你一个日期,让你求下一个回文日期和ABABBABA型回文日期是什么
基础方法会是什么呢?
观察数据规模,为10000101 \le N \le 89991231,是能够被遍历的,这是一点,在后面程序运行中可以从给定的日期开始对后面逐个遍历得到下一个回文日期和ABABBABA型回文日期
如何得到下一个回文日期?
首先明白回文日期的构造,回文日期最重要的是年份,年份知道了,那月份和日就呼之欲出了,所以我们只遍历月份就行了,但是不一定全部年份都对应一个合法的月和日,由于日数必须由月数决定,所以我们先处理月数,月只有1到12月,也就是说对年份的最后2个数字有要求,它只能取:{21,11,01,90,80,70,60,50,40,30,2o,10}这12个数,同样的日最多只有31天,对于一些特殊的月份,比如说闰年和平年的月份分别只有29天和28天,二月份等月份只有30天等,我们要进行区分,也就是说年份的前两个数字有一个都可以满足的交集:{10,20,30,40,50,60,70,80,90,01,11,21,31,41,51,61,71,81,91,02,12,22,32,42,52,62,72,82}这些不管在什么月份都是合法的,其他的月我们使用if进行判断,对大于这个月的日数最大值的年份我们就要抛弃,对于像2月这种特殊月份,我们就创造一个函数,输入年份,当函数返回1时为闰年,日最大值为29,0时为平年,日最大值为28,依次循环下去,遇到一个回文日期之后就跳出循环,这样子就能拿到回文日期了
那ABABBABA型回文日期怎么办呢?
ABABBABA型回文日期必须要求年份的前两个字母与后两个字母相同,当一个回文日期经过检验合法之后来到程序的末端,这时候判断是不是年份的前两个字母和后两个字母相同,如果相同则变量 abab 就等于该年份
那题目说的是要最近的回文日期和最近的ABABBABA型回文日期,你要怎么确定呢?
最近的ABABBABA型日期可能出现在最近的回文日期的后面也可能是最近的回文日期的本身,如果出现最近回文日期的后面,我必须要保证最近的回文日期保持最近不变而求得ABABBABA型回文日期,我用了一种办法,在循环的一开始定义一个变量cnt并令其为0,在循环中判断只有当cnt = 0 时ans才能接受回文日期,接受后cnt++,以后再有回文日期因为cnt!=0了,所以就不会错误地写入到ans中去,这里保证了ans只能写入一次最近的回文年,也同时标定了如果找到了最近的回文日期,cnt就会大于0,ABABBABA型日期的判断也并不复杂,如果变量abab不等于0了,就代表着ABABBABA型日期已经被找到了,当两个同时找到时,也就是条件cnt>0和abab>0同时成立,就可以输出两个变量的值了
构造法从给定的年份开始往后遍历,这样子就能解决掉错误地输出前面日期的情况了
以上就是构造法的全部思路
下面是执行代码(代码并不完全,测试过代码只能通过90%的样例,bug还没找出来@~@)
<code>#include <stdio.h>
int is_leap(int year)//判断闰年的函数
{
if(year%4==0 && year%100!=0)
{
return 1;
}else if(year%400 == 0)
{
return 1;
}else return 0;
}
int main(void)
{
int year,year_k,year_t,re_year,year_in,cnt;//cnt回文日期的标定
//year:循环年 year_k:年前两位数的千形式 year_t:年后两位数的十形式
//re_year:年的倒置形式 year_in:题目年的输入
long long int date;
scanf("%lld",&date);
year_in = date/10000;
for(year=year_in,cnt=0;year<9000;year++)
{
year_t = (year/100)%10*10+year/1000;
if(year%100<10)
{
year_k = (year%100)*1000;
}
else year_k = ((year%100)%10*10+(year%100)/10)*100;
re_year = year_k + year_t;
// printf("%d\n",re_year);
int month = re_year/100;
int day = re_year%100;
if(month>12 || month<1)
{
continue;
}
// else printf("%d\n",month);
if(month>=7 && month%2 ==0)
{
if(day>31) continue;
// else printf("%d",day);
}
else if(month >=7 && month%2 != 0)
{
if(month == 7 && day>31) continue;
else if(month != 7)
{
if(day>30) continue;
}
// else printf("%d",day);
}
else if(month <7 && month%2 ==0)
{
if (month == 2)
{
if(is_leap(year))
{
if(day>29) continue;
// else printf("%d\n",day);
}
else
{
if(day>28) continue;
// else printf("%d\n",day);
}
}
else
{
if(day>30) continue;
// else printf("%d\n",day);
}
}
else if(month < 7 && month%2 !=0)
{
if(day>31) continue;
// else printf("%d\n",day);
}
long long int ans,abab=0;//ans:最近回文日期答案 abab:最近ABABBABA型回文年答案
if(cnt == 0)
{
ans = year*10000 + re_year;
cnt++;
}
if(year_k/100 == year_t)
{
abab = year*10000 + re_year;
}
if(date == ans || date == abab)//如果题目输入日期与输出日期相同,跳过这个日期
{
cnt = 0;
continue;
}
if(abab!=0 && cnt>0)
{
printf("%lld\n",ans);
printf("%lld\n",abab);
break;
}
}
return 0;
}</code>
评论(0)
暂无评论