微软python有证书考吗_微软2017笔试第一题AC代码及思路(Python)

思路源自@gtdzx https://hihocoder.com/discuss/question/4295,优化参考下面@Chanson的回答

这道题包括两部分知识,概率知识和一些优化的技巧。

概率部分

1、取每件物品之间是独立事件,因为取得第 i件物品的概率仅由公式⌊P/(2^i)⌋%决定

2、取得i件物品所需quest 的期望 = 取得每件物品所需的quest期望之和

或者理解为取得i件物品所需quest 的期望 = 取得i-1件物品所需quest 的期望 + 取得第 i件物品所需quest 的期望

因此,解决原问题的关键在于计算取得每件物品的所需quest 的期望:其递归关系为

取得物品的所需quest 的期望 = 本次取到物品所需quest 的期望 + 本次未取到物品所需quest 的期望,

即E(p, q, quest) = p * quest + E(p+q, q,quest+1), p为本次取到物品的概率,quest为当前quest 次数, q为增长的概率。

最后,再将取得每件物品所需的quest期望相加即可。

优化部分

本题可能会遇到两种错误,RE和TLE,RE可能是由于递归过深爆栈所至,TLE就是超时啦

当单纯的采用递归来解本题,见分隔线下的代码,会导致RE。这是因为递归次数取决于递归函数中物品数量item和取得物品的概率p两个参数,当待取物品数量N很大,每次增加的概率Q很小时,递归必然会很深。

当采用上述思路时,见AC代码,递归次数仅取决于取得物品的概率p一个参数(因为只计算取得1件物品的quest 期望),相对来说递归次数会减少,不会出现RE,但会出现TLE。

为了解决TLE,需要做的优化如@Chanson的回答

获得item超过7时每多获得一个item所需次数的期望就相同了,如果只对前6个item进行计算,其他的都用固定的期望乘以剩下的个数,就可以很大程度上降低复杂度了。

最终AC代码

P, Q, N = (int(i) for i in raw_input().split())

def cal_quest_expectation(p, q, quest):

'''

used to calculate quest expectation for getting one item

'''

if p >= 100: return quest * 1

get_item = quest * p / 100.0

not_get_item = (100 - p) / 100.0 * cal_quest_expectation(p + q, q, quest + 1)

return get_item + not_get_item

res = 0

p = P

for i in xrange(N):

if i == 6:

res += (N - i) * cal_quest_expectation(0, Q, 1)

break

res += cal_quest_expectation(p, Q, 1)

p //= 2

print res

——————————————原帖————————————————————————

本地测试下,一个raw_input()操作大约6000ms

附:一题RE代码

get_p, q, num = (int(i) for i in raw_input().split())

def cal(item, quest, p, flag):

if p == 0: return 0

if item == num:

return quest * p / 100.0

if flag:

new_p = get_p // (2 ** item)

else:

new_p = min(100, p+q)

return p*(cal(item+1, quest+1, new_p, True)/100.0) + p*(cal(item, quest+1, 100-new_p, False)/100.0)

print cal(1, 1, get_p, True) + cal(0, 1, 100-get_p, False)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值