NOIP模擬 取書問題【概率期望dp】
阿新 • • 發佈:2018-12-17
題目描述
有n個同學坐成一列,按從前往後的順序傳n本書,第i本數是第i新的,其中第i個同學會從n-i+1本課本中選一本並把剩下的書傳給後面的一位同學,第i個同學在挑選課本的時候滿足 如下過程:
1.如果只剩一本書,則一定拿走,否則轉步驟2;
2.從剩下的數中抽出最新的一本。
3.有a[i]的概率選擇這本書並結束選擇,1-a[i]個概率將這本書傳給後面的同學並回到步驟1。
現在問最後一名同學拿到的數在新舊排名的期望。
傳送門:http://www.accoders.com/problem.php?cid=1697&pid=2
解題思路
考慮一般的演算法瓶頸在我們需要記錄拿走的書的集合,但如果我們知道最後一位同學拿的書的排名為 x,那麼排名在 x 之前的書對 x 產生的貢獻只與剩餘的本數(因為一個人拿每本書的概率是相同的)有關,排名在 x 之後的同理。
所以我們先列舉最後一位同學拿的書的排名 x,再考慮 DP 概率,記 f[i][j][k]表示前i 個同學拿書時還剩下 j 本書排名小於等於 x,k 本書排名大於 x,可以轉移到 f[i+1][j-1][k]或f[i+1][j][k-1],轉移係數為第i個同學拿前j-1新的書的概率和拿後k新的書(不能拿第x本),可以O(n2n2)預處理後轉移係數做到 O(1)轉移,f[n][1][0]就是最後一個同學拿 x 的概率。
時間複雜度 O(n4),期望得分 80 分。
最後我們發現在確定 x,i,j 後,k 的值是可以算出的,所以省去一維狀態。
時間複雜度 O(n3),期望得分 100 分。
附上程式碼
#include<bits/stdc++.h> const int N=303,M=1000000007; int n,x,p[N][N]; long long f[N],now,ans; int main() { scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d",&x); p[i][1]=x,now=1-x; for(int j=2;j<=n-i;j++) { p[i][j]=(p[i][j-1]+now*x)%M; now=now*(1-x)%M; } p[i][n-i+1]=1; } for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<n;i++) for(int j=1;j<=n-i;j++) f[j]=(f[j]*(1-p[i][j])+f[j+1]*p[i][j])%M; printf("%d",(f[1]+M)%M); return 0; }
若您覺得此篇部落格寫得不錯,請別忘了點贊並關注我哦 >_<