UVA11762概率期望

 1 /*UVA11762*/
 2 /*概率期望:
 3 题目:给出一个整数n,每次可以在不超过n的素数中随机选择一个p,如果p是n的约数,则n变成n/p,否则不变。
 4 问平均情况要多少次随机选择,才能把n变成1?
 5 解题步骤:举例、归纳方法
 6 举例:
 7 例N=13 ,可得素数2,3,5,7,11,13, 发现只有选到13时才能变成1,ans=1/p,p=1/6,ans=6;
 8 例N=15, 可得素数2,3,5,7,11,13,发现只能选到3,5;
 9          若选到3,N=5,素数2,3,5, 必须要选到5
10          若选到5,N=3,素数2,3,  必须选到3
11          p=(1/6)*(1/3)+(1/6)*(1/2) ans=1/p=36/5
12 归纳:
13 关键是求p(由上可看出是运用乘法,加法原理)
14 递归方法:f(N)=sigm求和(1/Q[N]*f(N/i),2<=i<=N且i是素数且N%i==0),N>1;
15                1,N=1;
16           注意f(N)可以记忆化
17           Q[N]=不超过n的素数的个数,例Q[15]=6,可预先求出
18 但是可惜,上面的方法错了= =,换句话说,p是对的,而1/P不是答案
19 改之:马尔可夫过程
20 f(x)=1+f(x)*(Q(x)-g(x))/p(x)+sigm(f(x/y)/Q(x),y是素数因子,g(x)是y的总个数
21 移项后化简:f(x)=(sigm(f(x/y))+Q(x))/g(x)
22 */
23 #include<iostream>
24 #include<stdio.h>
25 #include<string.h>
26 #include<algorithm>
27 #include<stdlib.h>
28 #include<math.h>
29 #include<queue>
30 #include<vector>
31 #include<map>
32 
33 using namespace std;
34 
35 const int maxn = 1000000;//素数打表
36 bool flag[maxn+5];
37 int prim[maxn/3], cnt;
38 void calc_prim(){
39     cnt=0;
40     for(int i = 2; i <= maxn; i ++){
41         if(!flag[i]) prim[cnt++] = i;
42         for(int j = 0; j < cnt && prim[j]*i <= maxn; j ++){
43             flag[i*prim[j]] = 1;
44             if(i%prim[j]==0) break;
45         }
46     }
47     return ;
48 }//最终有cnt个素数prim[0]--prim[cnt-1]
49 int Q[maxn+5];
50 void builtQ()
51 {
52     calc_prim();
53     Q[2]=1,Q[3]=2;
54     for(int i=4;i<=maxn;i++)
55     if (!flag[i]) Q[i]=Q[i-1]+1;else Q[i]=Q[i-1];
56     //利用了素数非连续性的特点
57     /*Q[x]=Q[x-1]+1,if x is prime,else Q[x]=Q[x-1]*/
58 }
59 double F[maxn+5];//记忆化搜索用
60 double sigmp(int N)
61 {
62     if (F[N]!=-1.0) return F[N];
63     double sum=0;int tot=0;
64     for(int i=2;i<=N;i++)
65     {
66         if (!flag[i] && N%i==0) sum+=sigmp(N/i),tot++;
67     }
68     sum=(sum+Q[N])/tot;//累加上无法约简的部分
69     return F[N]=sum;
70 }
71 int main()
72 {
73     int t,N;
74     builtQ();
75     /*memset(F,-1,sizeof(F));*/
76     /*double 可以初始化为0,但不可以为-1*/
77     for(int i=2;i<=maxn;i++) F[i]=-1.0;
78     F[1]=0.0;
79     cin>>t;
80 
81     for(int cas=1;cas<=t;cas++)
82     {
83         cin>>N;
84         printf("Case %d: %.7lf\n",cas,sigmp(N));
85     }
86     return 0;
87 
88 }

 

posted @ 2014-02-26 21:22  little_w  阅读(217)  评论(0编辑  收藏  举报