特殊日期
原题
对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 年 月 日至 年 月 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
例如, 年 月 日满足要求,因为 。
请提交满足条件的日期的总数量。
分析
这题关键在于枚举符合条件的“日期”(年份的各个数位上的数字之和=月、日的数位数字之和),若一一枚举出题意范围内的日期,时间复杂度太大,不切实际。所以我们需要压缩枚举的范围。
首先,月、日的数位数字之和的最大值和最小值可以人为确定下来,分别为20和2(分别由9月29日和1月1日两个日期得出),因为许多年份的各个数位上的数字之和是大于20的,所以可以直接排除这些年份。
其次,不管哪一年,日期种类数不会超过12*31=372种,所以这里先把这372种日期(月、日)及其各个数位上的数字之和的值枚举出来,然后枚举一定范围内的年份,将符合条件的日期(年、月、日)枚举出来。具体实现见如下代码和详细注释。
源码
# 特殊日期
import datetime
sum_min = 2
sum_max = 20 # 月、日最大的数位和,9月29日(0929,9+2+9=20)
# 将每个月份中的每天(month,day)和数位和sum_存储在字典dict_sum2days中
dict_sum2days = {}
# 初始化字典
for sum_ in range(sum_min,sum_max+1):
dict_sum2days[sum_] = []
# sum_(范围在[sum_min,sum_max])作为“键”,存放(month,day)的列表作为“值”
# 一年12*31天(为方便统计,假设一个月31天,后续再排除不存在的日期)
for month in range(1,13):
for day in range(1,32):
sum_ = sum( map(int,str(month)+str(day)) ) # 计算月、日的数位和
dict_sum2days[sum_].append( (month,day) )
count = 0
# 遍历年份
for year in range(1900,9921):
sum_ = sum( map(int,str(year)) )
if sum_ > sum_max:
continue
# 取出与当前 年份的各个数位上的数字之和相等的月、日(m,d)
for m,d in dict_sum2days[sum_]:
# 使用“异常”排除不存在的日期
try:
datetime.date(year,m,d) # 若日期(year,m,d)不存在,该语句将报错,except语句捕捉后跳过该日期
count += 1
except:
continue
print(count)
特殊时间
原题
源码
解题思路其实和上一题“特殊日期”有许多相似之处,算法具体实现如下。
import datetime
def is_legal_str(s: str):
'''判断一个字符串是否是满足条件的字符串'''
if len(set(s)) == 2:
num = s.count(s[0])
if num == 1 or num == 3:
return True
return False
month_day_l = [] # 满足条件的月和日组成的4位数序列(先统一考虑所有月份都为31天)
# 其实不用遍历到31天,因为不存在可以组合成满足条件的“4位数”
for m in range(1,13):
for d in range(1,32):
# 日期字符串(月、日)
date_str = "%02d%02d" % (m,d)
# 判断该日期字符串是否满足条件
if is_legal_str(date_str):
month_day_l.append( (m,d,date_str) )
date_l = [] # 满足条件的日期字符串(年、月、日)
for year in range(9999):
year_str = "%04d"%year
if is_legal_str(year_str):
for m,d,date_str in month_day_l:
try:
datetime.date(year,m,d)
except:
continue
# 要保证两个“4位数”由相同的两种数字组合
if sorted(year_str) == sorted(date_str):
date_l.append(year_str+date_str)
count = 0
# res_l = [] # 存储满足条件的时间
# 时间范围: 00:00 ~ 23:59
for h in range(24):
for m in range(60):
# 时间字符串,22时02分,形如2202
time_str = "%02d%02d"%(h,m)
# 判断该时间字符串是否满足条件
if is_legal_str(time_str):
for date_str in date_l:
if sorted(date_str[:4]) == sorted(time_str):
count += 1
# res_l.append(date_str+time_str)
print(count)
上一篇:蓝桥杯备战日志(Python)22-最小权值&本质上升序列-(二叉树的形式、动态规划)