题目链接: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可以节约时间。
【代码】
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std; typedef long long ll;
const int N = 1e6+; double f[N];
vector<int> ps;
int n,vis[N],isp[N]; void get_primes() {
memset(isp,,sizeof(isp));
for(int i=;i<=N;i++) if(!isp[i]) {
ps.push_back(i);
if((ll)i*i<=(ll)N)for(int j=i*i;j<=N;j+=i) isp[j]=;
}
} double dp(int x) {
if(x==) return ;
if(vis[x]) return f[x];
vis[x]=;
f[x]=0.0; int g=,p=;
for(int i=;i<ps.size() && ps[i]<=x;i++) {
int y=ps[i]; p++;
if(x%y==) g++ , f[x]+=dp(x/y);
}
f[x]=(f[x]+p)/g;
return f[x];
} int main() {
get_primes();
int T,kase=;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
printf("Case %d: %.10lf\n",++kase,dp(n));
}
return ;
}