1. 程式人生 > 其它 >D. Jon and Orbs (概率dp)

D. Jon and Orbs (概率dp)

技術標籤:DP

D. Jon and Orbs (概率dp)


題意:給定 k k k種龍晶, q q q個詢問,每天產生一種龍晶,產生每種龍晶概率相等,每個詢問給定 p p p,求產生 k k k種龍晶的概率 ≥ ( p − ε ) 2000 \ge \dfrac{(p-\varepsilon)}{2000} 2000(pε) 的最小天數。


思路:概率 d p dp dp,令 d p [ i ] [ j ] dp[i][j] dp[i][j]表示第 i i i天產生 j j j種龍晶的概率,有轉移方程: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] × j k + d p [ i − 1 ] [ j − 1 ] × k − ( j − 1 ) k dp[i][j]=dp[i-1][j]\times \dfrac{j}{k}+dp[i-1][j-1]\times \dfrac{k-(j-1)}{k}

dp[i][j]=dp[i1][j]×kj+dp[i1][j1]×kk(j1)

因為天數不確定,可開足夠大的第一維,或者滾動陣列去掉第一維,裡層迴圈倒著轉移即可。

然後每次求出第 i i i天的情況後,預處理出 a n s [ p ] ans[p] ans[p]陣列。

需要注意的是 d p [ i ] [ 0 ] = ( i = = 0 ) 1 : 0 dp[i][0]=(i==0)1:0 dp[i][0]=(i==0)1:0


程式碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream> using namespace std; typedef long long ll; const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7; #define mst(a,b) memset(a,b,sizeof a) #define PII pair<int,int> #define fi first #define se second #define pb push_back int k,q; double dp[N]; int a[N]; int main(){ scanf("%d%d"
,&k,&q); dp[0]=1; for(int i=1,p=1;p<=1000;i++){ for(int j=k;j;j--) dp[j]=dp[j]*j/k+dp[j-1]*(k-j+1)/k; while(p<=1000&&dp[k]*2000>=p-1e-7) a[p++]=i; dp[0]=0; } while(q--){ int p;scanf("%d",&p);printf("%d\n",a[p]); } return 0; }