1. 程式人生 > >LightOJ 1038 Race To 1 Again(概率DP)

LightOJ 1038 Race To 1 Again(概率DP)

eve any error sqrt str 分享圖片 rep show return

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

. He repeats this procedure until D becomes 1. What is the expected number of moves required for N to become 1.

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

will be ignored.

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)