这两个问题都太短太简单了,干脆放在一起了。原书分别位于1.1和1.7章节。
问题一描述
一辆卡车违反交通规则,撞人后逃跑。现场有三人目击事件,但都没有记住车号,只记下车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的,但与前两位不同; 丙是数学家,他说:四位的车号刚好是一个整数的平方。请根据以上线索求出车号。
分析
根据以上线索,可以得到以下几个条件:
1. 车号是4位整数
2. 车号的千位与百位相同,十位与个位数字相同,但彼此不同
3. 车号是另一个整数的平方
很自然地,我们可以根据条件3想到去遍历平方数是四位数的整数(条件1),然后判断这个平方数是否符合条件2,那么如何决定遍历区间呢?由条件1可以想到,四位整数的范围是1000到9999,而结合条件2,这个四位数的范围又可以缩小到1100到9988。第这两个边界数字进行开平方运算,对结果取整,得到范围是33到99。所以我们只要计算33到99的平方,然后将结果对比条件2,符合条件即为结果。于是编写代码如下:
for i in range(int(1100**0.5),int(9988**0.5)+1):
s = i**2
a, b = s//100, s%100 # 拆分为前两位和后两位
if a!=b and a%11==0 and b%11==0: # 如果一个两位数的个位和十位相同,则必能被11整除
print(f"车号为:{s}")
此外,验证条件2,我们也可以将四位数转成字符串,然后进行字符串的比较,不过因为要调用每个位置的数字,这样写稍微麻烦一点。当然,如果符合条件,我们也不需要再将结果转成数字,直接输出即可。代码如下:
for i in range(int(1100**0.5),int(9988**0.5)+1):
s = str(i**2)
if s[0]!=s[2] and s[0]==s[1] and s[2]==s[3]:
print(f"车号为:{s}")
当然,换个角度,我们也可以先把所有符合条件2的4位数找出来,然后依次判断其是否是某一个整数的平方,从而找到答案。
for a in range(1,10):
for b in range(10):
if a==b:
continue # 如果千位百位与十位个位相同,则跳过
s = a*1100+b*11
if int(s**0.5)==s**0.5: # 判断该四位数开平方后是否是一个整数
print(f"车号为:{s}")
当然,常识的数学判断,可以知道b不可能取0,所以也可以写成for b in range(1,10)。
另外,根据该应用的常识判断,应该是有唯一解(不然抓不了交通肇事犯),所以在代码找到符合条件的数字后,可以不用继续后面的运算,直接break返回。
输出
车号为:7744
问题二描述
假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱,他打算在今后5年中的每年年底取出1000元,到第5年时刚好取完,请算出他存钱时应存入多少。
分析
这题是一道简单的数学题,和算法其实扯不上边,硬要编程的话,也只是把程序当做计算器那样进行数学计算而已。
已知第五年底刚好取完存款,说明第五年的利息加本金正好1000,按照这个办法逆推即可。月息0.63%,则年息0.63%*12(如果没有特殊计算年息的要求的话),所以:
第五年初的本金*(1+0.63%*12) = 1000
第四年初的本金*(1+0.63%*12) = 第五年初的本金+1000
第三年初的本金*(1+0.63%*12) = 第四年初的本金+1000
第二年初的本金*(1+0.63%*12) = 第三年初的本金+1000
第一年初的本金*(1+0.63%*12) = 第二年初的本金+1000
要求存钱时该存多少,也就是第一年初的本金,依次倒着计算五次就好。代入公式转换一下,就是每年末剩余的钱加上1000除以年息。
代码如下:
interest = 1+0.0063*12
y = 5
money = 0
while y>0:
money = (1000+money)/interest
y -= 1
print(round(money,2),"元")
输出
4039.44 元