思路源自@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)