LightOJ 1038 Race To 1 Again(概率DP)
Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.
In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case begins with an integer N (1 ≤ N ≤ 105).
Output
For each case of input you have to print the case number and the expected value. Errors less than 10-6
Sample Input
3
1
2
50
Sample Output
Case 1: 0
Case 2: 2.00
Case 3: 3.0333333333
題解:題意就是給你一個數,然後你每次可以執行的操作為,將這個數除以它的因子(包含1和他本身),然後再將結果賦給他本身,直到變成1;
讓你求執行次數的期望;
設DP[num]:表示數字num變為1執行次數的期望;
則: dp[num]=(dp[x1]+1)/n+(dp[x2]+1)/n+(dp[x3]+1)/n+...+(dp[xn]+1)/n;(其中xn==num)
則dp[num]=(sigma(1,n-1) xi + n)/(n-1);
參考代碼:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define clr(a,val) memset(a,val,sizeof(a)) 4 const int maxn=1e5+10; 5 int T,n; 6 double dp[maxn]; 7 8 void prework() 9 { 10 clr(dp,0); 11 for(int i=2;i<maxn;++i) 12 { 13 int step=sqrt(i),num=-1; 14 double sum=0; 15 for(int j=1;j<=step;++j) 16 { 17 if(i%j==0) 18 { 19 sum+=dp[j]+1,num++; 20 if(j!=i/j) sum+=dp[i/j]+1,num++; 21 } 22 } 23 dp[i]=sum*1.0/num; 24 } 25 } 26 27 int main() 28 { 29 prework(); 30 scanf("%d",&T); 31 for(int cas=1;cas<=T;++cas) 32 { 33 scanf("%d",&n); 34 printf("Case %d: %.7lf\n",cas,dp[n]); 35 } 36 37 return 0; 38 }View Code
LightOJ 1038 Race To 1 Again(概率DP)