标签:integer std tin ++ gen 复杂 opened one ber
Little Hi is playing a video game. Each time he accomplishes a quest in the game, Little Hi has a chance to get a legendary item.
At the beginning the probability is P%. Each time Little Hi accomplishes a quest without getting a legendary item, the probability will go up Q%. Since the probability is getting higher he will get a legendary item eventually.
After getting a legendary item the probability will be reset to ?P/(2I)?% (?x? represents the largest integer no more than x) where I is the number of legendary items he already has. The probability will also go up Q% each time Little Hi accomplishes a quest until he gets another legendary item.
Now Little Hi wants to know the expected number of quests he has to accomplish to get N legendary items.
Assume P = 50, Q = 75 and N = 2, as the below figure shows the expected number of quests is
2*50%*25% + 3*50%*75%*100% + 3*50%*100%*25% + 4*50%*100%*75%*100% = 3.25
题意:要获取 N 个物品(1e6个),初始获得概率是 P %,每当上次没有获取,这次的获得概率会线性增加 Q%,直至达到 100% 则必定获取。而每当获取一个时,下一次的初始概率会下降,降低至 P / (2^l)%,l 是已经获取的个数,P 是之前给定的初始概率。问获取 N 个的期望次数是多少。
这个题大概是微软的一道笔试题吧,貌似数据是随机的所以没有极限数据,我dfs+结论卡过去了一遍,后来又发现正解。
由于后面的初始概率是按照已获取的个数定的,个数越多概率越小,由于题目最开始的 p 最大仅100,因此至多 7 层之后初始概率就都是 0 了。
我最开始考虑当概率是 0 的时候,毫无疑问,每获取一个的次数期望都是固定的,我可以用一次循环直接求出这个期望次数。然后就通过类似图中的概率树的 dfs ,每当遇到一个下一次初始概率为 0 的位置时,就可以直接加上剩余需要获取的个数*获取每一个的期望,后面就不用 dfs 下去了。
这种做法其实就可以通过这题的数据了。但是这样做通不过大数据,100 1 1000000
当然,按照上述思路拓展一下,我们同样可以求出概率是任意值时获得下一个的期望,因为这个概率的范围只有 0~100 。其实我们发现图中那两个标号 1 的节点子树是一样的,它们获取下一个物品的情况和期望都是一样的。我本来在考虑不同情况下拿到第一个,开始拿第二个,第二个和第一个是不是独立的?但是其实所有情况下拿到第一个的概率总和是1,所以无论 dfs 的哪一个分支,最后都会到同一个初始概率去获取第二个,所以获取第二个的期望与第一个是独立可加的,所以我计算出所有初始概率下获取一个的期望,然后对于初始概率 P 跑一个循环,累计期望,然后计算下一次的初始概率,直到下一次的初始概率为 0 ,那么后面的就直接个数乘期望就能跳出循环了。
因此这样做复杂度大概就是 O(100*100+7)
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn=1e6+5; 8 const int INF=0x3f3f3f3f; 9 const int mod=1e9+7; 10 double ans=0; 11 double num[105] = {0}; 12 int n,p,q; 13 14 int main(){ 15 scanf("%d%d%d",&p,&q,&n); 16 for(int pre = 0 ; pre <= 100 ; ++ pre ){ 17 int cnt = 0; 18 double p1 = 1; 19 while(1){ 20 double xq = ( pre + cnt * q) / 100.0; 21 if( pre + cnt * q >= 100 ){ 22 num[pre] += ( cnt + 1 ) * p1 ; 23 break; 24 } 25 num[pre] += p1 * xq * ( cnt + 1 ); 26 p1 *= ( 1 - xq ); 27 cnt++; 28 } 29 } 30 31 int pre = p; 32 for(int i = 1 ; i <= n ; ++ i ){ 33 if( pre == 0 ){ 34 ans += ( n - i + 1 ) * num[0]; 35 break; 36 } 37 ans += num[pre]; 38 pre >>= 1; 39 } 40 41 printf("%.2lf\n",ans); 42 return 0; 43 }
hihocoder1489 Legendary Items 概率期望
标签:integer std tin ++ gen 复杂 opened one ber
原文地址:http://www.cnblogs.com/cenariusxz/p/6703253.html