一開始的想法很單純,答案就是題目給的浮點數。
後來想想發現,第i個人擲骰,i未必為1,
而也未必在第一輪就骰出。
所以我想的太簡單了 -.-。
所以正確的思考方式應該為:
n個人中第k個人骰贏得機率是多少?
此人可能在第一輪骰贏、第二輪骰贏、第三輪骰贏……一直到他骰贏的那輪為止。
假設骰贏的機率為p,沒骰贏的機率為q = p - 1
第k個人要骰贏,前面k-1個人一定不會骰贏:
q ^ (k-1)
此人自己需骰贏:
q ^ (k-1) * p
如果他沒骰贏,遊戲被迫進入第二輪,
即第一輪大家都沒骰贏:
q ^ n
第二輪中他骰贏的情況(第一輪沒人贏,第二輪他贏):
(q ^ n) * q ^ (k-1) * p
第三輪中他骰贏的情況(前二輪沒人贏,第三輪他贏):
(q ^ 2n) * q ^ (k-1) * p
類推,到第x+1輪他骰贏的情況(前x輪沒人贏,第x+1輪他贏):
(q ^ xn) * q ^ (k-1) * p
所以若要計算他所有骰贏的可能情況,
就是第一輪骰贏的機率 + 第二輪骰贏的機率 + ... + 第x輪骰贏的機率:
q ^ (k-1) * p + (q ^ n) * q ^ (k-1) * p + (q ^ 2n) * q ^ (k-1) * p + ... + (q ^ xn) * q ^ (k-1) * p
以下化簡原式:
- q ^ (k-1) * p [1 + (q ^ n) + (q ^ 2n) + ... + (q ^ xn)] (取出q ^ (k-1)*p)
- 1 + (q ^ n) + (q ^ 2n) + ... + (q ^ xn) 是無窮等比級數(根本就不知道他哪一輪會贏)
所以2.式可以化簡為1 / (1 - q ^ n)(查詢等比級數公式/無窮等比級數公式)
原式化簡為:
[q ^ (k-1) * p] / (1 - q ^ n)。
另外要注意,當p為0時,此公式分母為0,所以輸出需另外處理。
(就是輸出0.0000而已啦)
/* ACM 10056 * mythnc * 2011/10/13 11:47:52 * run time: 0.008 */ #include <stdio.h> #include <math.h> int main(void) { int set, n, k; /* n players, the kth player */ double p; scanf("%d", &set); while (set-- > 0) { scanf("%d %lf %d", &n, &p, &k); if (p == 0.0) { printf("0.0000\n"); continue; } if (k == 1) printf("%.4f\n", p / (1 - pow(1-p, n))); else printf("%.4f\n", p * pow(1-p, k-1) / (1 - pow(1-p, n))); } return 0; }
1 則留言:
寫的很清楚!!!! 不像其他人都只提一點點就直接貼程式碼
張貼留言