问题描述
如果一个日期中年月日的各位数字之和是完全平方数,则称为一个完全日期。
例如:2021年6月5日的各位数字之和为2+0+2+1+6+5=16,而16是一个完全平方数,它是4的平方。所以2021年6月5日是一个完全日期。
例如:2021年6月23日的各位数字之和为2+0+2+1+6+2+3=16,是一个完全平方数。所以2021年6月23日也是一个完全日期。
请问,从2001年1月1日到2021年12月31日中,一共有多少个完全日期?
答案提交
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案是只填写这个证书,填写多余的内容将无法得分。
纵观网上的答案,基本都是采用datetime函数,用一种十分简洁方便的算法计算出来,但是在比赛的过程中,不知道有这个函数的选手,要如何应对这样的题目呢?
很不幸,我就是这种选手,终究是练习太少,对很多实用的函数不太了解,甚至不知其的存在!
所以我采用了笨方法做出了这道题~
ans = 0 # 结果计数器
# 很明显 最大的日期应该是2019/9/29日,也就是加起来32
# 而最小的日期应该是2001/1/1日,也就是加起来5
# 5-32之间的完全平方数只有以下三个
lists = [9, 16, 25]
for i in range(1, 22): # 枚举1到21年
count = 2 # 2001中的2是固定不变的,所以直接放进count中
for y in str(i): # 把年份加进去
count += int(y)
for j in range(1, 13): # 枚举月
for m in str(j): # 把月份加进去
count += int(m)
for x in range(3): # 枚举日期的十位数 0-2 3以上比较特殊,要拎出来单独算
count += x
for k in lists: # 如果k - count为一个合法的个位数,则说明该日期成立
if x == 0 and 0 < k - count <= 9: # 如果x为0,那么个位数就不能为0
ans += 1
elif x != 0 and 0 <= k - count <= 9:
ans += 1
count -= x # 记得减去刚刚加的x
# 下面就开始计算30、31的情况
if j in [1, 3, 5, 7, 8, 10, 12]:
count += 3
for k in lists:
if 0 <= k - count <= 1:
ans += 1
count -= 3
elif j in [4, 6, 9, 11]:
count += 3
for k in lists:
if k - count == 0:
ans += 1
count -= 3
for m in str(j):
count -= int(m)
# 减去刚刚加多的2月29日
runn = [4,8,12,16,20]
for i in range(1,21):
count = 15
if i not in runn: # 不是闰年
for j in str(i):
count += int(j)
if count in lists:
ans -= 1
print(ans)
如果采用函数进行计算,就会变得简洁方便:
import datetime
start = datetime.datetime(year=2001, month=1, day=1)
end = datetime.datetime(year=2021, month=12, day=31)
res = 0
for i in range(1, (end - start).days + 1): # (end - start).days 计算出时间差多少天
cur = start + datetime.timedelta(i) # 还原出日期
# print(cur) # 2001-01-02 00:00:00
s = str(cur.year) + str(cur.month) + str(cur.day)
print(s) # 200112
n = sum(list(map(int, s)))
if n in [9,16,25]:
res += 1
print(res)