lg2010传送门

题目大意:

给出两个时间点
如:20190815(正好今天)
20001201(随便取的)
求出两个时间点之间(包括这两个时间点)的时间有几个是回文的
如:20111102(当然还有其它)
而且题目保证两个时间点都为真实年份,也就是年份一定为4位数,月份和日期不到2位前都会补0

需要注意的点:

1. 保证输入的第一个年份小于等于第二个(废话)
2. 要判断闰年与平年,还要判断大月与小月和2月(1月大,2月小,3月大,4月小……) 咳咳,是人都知道,但还是要讲一下
它们的区别:
其中:
  • 1,3,5,7,8,10,12月每个月有31天;
  • 4,6,9,11月每个月有30天;
  • 而对于2月,闰年时有29天,平年时有28天。
一个年份是闰年当且仅当它满足下列两种情况其中的一种:
  • 这个年份是4的整数倍,但不是100的整数倍;
  • 这个年份是400的整数倍。
例如:
  • 以下几个年份都是闰年:2000,2012,2016
  • 以下几个年份是平年:1900,2011,2014
所以可以得出如下判断闰年的代码:
1
2
3
4
5
6
7
8
9
if(y%400==0) //y为年份   返回true为闰年   反之平年
return true;
else
{
if(y%4==0&&y%100!=0)
return true;
else
return false;
}

很好理解!

接下来就是思路了:

总体思路就是暴力枚举!:D
反正我是枚举每一天,判断那一天的日期是不是回文的,如果是结果就加1,不是就跳过
这样的枚举代码肯定很长(我的就是)
所以一定要细心!

细心!

细心!

代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <bits/stdc++.h>
using namespace std;
int rn(int); //调用函数
int x,y,cnt=0,day=0,years,months,yeare,monthe;
int mds=0,mde=0; //x是开始时间 y结束
int s[9],e[9]; //cnt计数 years是开始年份 yeare是结束年份 //其它一样 mds和mde是临时变量(后面会讲)
bool tp=true,ttp=true; //判断变量
int main()
{
cin>>x>>y;
for(int i=8;i>=1;i--) //两个for循环将int类型拆为数组
{
s[i]=x%10;
x/=10;
}
for(int i=8;i>=1;i--)
{
e[i]=y%10;
y/=10;
}
for(int i=1;i<=8;i++) //特判两个日期是否一样
if(s[i]!=e[i])
tp=false;
int zip=8;//因为数据点说了60%的数据开始和结束时间一样
for(int i=1;i<=4;i++) //zip记录数组下标
if(s[i]!=s[zip--]) //分别前后判断
ttp=false; //只要有不同ttp就为false
if(tp) //假如输入数据相同且回文
if(ttp)
{
cout<<1; //直接输出1个回文并返回(程序结束)
return 0;
}
else //假如数据相同但不回文
{
cout<<0; //输出0个回文并返回(程序结束)
return 0;
}
//假如输入的两个数据不同 那就开始一堆操作了...
years=s[1]*1000+s[2]*100+s[3]*10+s[4];
yeare=e[1]*1000+e[2]*100+e[3]*10+e[4];
months=s[5]*10+s[6];
monthe=e[5]*10+s[6]; //将数组转为开始和结束的年和月
for(int i=months;i>=1;i--) //循环开始的月份次 如3月就循环3次
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12) //判断是否为大月
mds+=31;
if(i==4||i==6||i==9||i==11) //小月
mds+=30;
if(i==2&&rn(years)) //2月闰年
mds+=29;
else if(i==2&&!rn(years)) //2月平年
mds+=28; //mds记录开始月份转为天数有多少天
}
for(int i=monthe;i>=1;i--) //结束月份 道理同上
{
if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)
mde+=31;
if(i==4||i==6||i==9||i==11)
mde+=30;
if(i==2&&rn(yeare))
mde+=29;
else if(i==2&&!rn(yeare))
mde+=28;
}
day=(yeare-years)*365+(mde-mds)+10*e[7]+e[8]-10*s[7]-s[8]; //用结束减开始算出总天数
for(int i=1;i<=day;i++) //循环总天数遍
{
int temp=8; //记录下标
bool rb=true; //定义一个判断 如同上面的特判
for(int i=1;i<=4;i++)
if(s[i]!=s[temp--])
rb=false;
if(rb==true) //如果回文答案加1
cnt++;
s[8]+=1; //s[8]为天数 天数加1
if(s[8]>9) //下面为进位判断(不具体说明了)
{
s[8]-=10; //就是9变成10本身减9
s[7]++; //上一位加1
} //或12变13减12
int mo; //年份加1
int ye; //天数到达一定的数量月份加1
ye=s[1]*1000+s[2]*100+s[3]*10+s[4];//天数为1
mo=s[5]*10+s[6]; //天数较难判断
//因为有大小月和闰平年
if((mo==1||mo==3||mo==5||mo==7||mo==8||mo==10||mo==12)&&(s[7]*10+s[8])>31)
{
s[6]++;
s[7]-=3;
s[8]--;
}
if((mo==4||mo==6||mo==9||mo==11)&&(s[7]*10+s[8])>30)
{
s[6]++;
s[7]-=3;
}
if((mo==2)&&rn(ye)&&(s[7]*10+s[8])>29)
{
s[6]++;
s[7]-=3;
s[8]++;
}
if((mo==2)&&!rn(ye)&&(s[7]*10+s[8])>28)
{
s[6]++;
s[7]-=2;
s[8]-=8;
}
if(s[6]>9)
{
s[6]-=10;
s[5]++;
}
if((s[5]*10+s[6])>12)
{
s[4]++;
s[5]--;
s[6]-=2;
}
if(s[4]>9)
{
s[4]-=10;
s[3]++;
}
if(s[3]>9)
{
s[3]-=10;
s[2]++;
}
if(s[2]>9)
{
s[2]-=10;
s[1]++;
}
} //退出循环
cout<<cnt; //输出回文日期的个数
}
int rn(int y) //判断是否为闰年函数(上面讲过)
{
if(y%400==0)
return true;
else
{
if(y%4==0&&y%100!=0)
return true;
else
return false;
}
}
//结束啦!!ヾ(◍°∇°◍)ノ゙ヾ(゚∀゚ゞ)

所以这个困难又麻烦的题就结束了


注意:文章最终版权归墨痕所有,如要引用请告知,谢谢!

 评论


Copyright 2019 Mohen's blog | 博客内容仅供学习和研究使用,版权归作者所有

博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

次访问 | 人次 | 字数统计:14.1k
载入天数...载入时分秒...

BY-NC-SA 4.0