山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

UVA 11762 Race to 1(记忆化+期望)

 

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20869

 

【思路】

       DP+期望。

       设f[x]表示从x转移到1的期望操作次数,则有:

              f[x]=1+f[x]*(1-g[x]/p[x])+sigma(f[x][y])/p[x]

       进一步为:

              f[x]=(sigma(f[x/y])+p[x])/g[x]

       其中p[x]表示1..x的素数个数,p[x]表示素数中可以整除x的个数。

   保留vis可以节约时间。

【代码】

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N = 1e6+10;
 9 
10 double f[N];
11 vector<int> ps;
12 int n,vis[N],isp[N];
13 
14 void get_primes() {
15     memset(isp,0,sizeof(isp));
16     for(int i=2;i<=N;i++) if(!isp[i]) {
17         ps.push_back(i);
18         if((ll)i*i<=(ll)N)for(int j=i*i;j<=N;j+=i) isp[j]=1;
19     }
20 }
21 
22 double dp(int x) {
23     if(x==1) return 0;
24     if(vis[x]) return f[x];
25     vis[x]=1;
26     f[x]=0.0; int g=0,p=0;
27     for(int i=0;i<ps.size() && ps[i]<=x;i++) {
28         int y=ps[i]; p++;
29         if(x%y==0) g++ , f[x]+=dp(x/y);
30     }
31     f[x]=(f[x]+p)/g;
32     return f[x];
33 }
34 
35 int main() {
36     get_primes();
37     int T,kase=0;
38     scanf("%d",&T);
39     while(T--) {
40         scanf("%d",&n);
41         printf("Case %d: %.10lf\n",++kase,dp(n));
42     }
43     return 0;
44 }

 

posted on 2016-01-28 18:39  hahalidaxin  阅读(226)  评论(0编辑  收藏  举报