概率DP
比较精妙。
import java.util.*;
import java.io.*;
public class Main {
static boolean isPrimer[];
static int l=0;
static int len=1000010;
static int primer[];
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static double find[];
public static void main(String[] args) throws Exception{
int t=getInt();
isPrimer=new boolean[len];
primer=new int[len];
find=new double[len];
for(int i=2;i<len;i++)
if(!isPrimer[i])
for(int j=2;i*j<len;j++)
isPrimer[i*j]=true;
for(int i=2;i<len;i++) {
if(!isPrimer[i])
primer[l++]=i;
}
for(int c=1;c<=t;c++) {
int n=getInt();
double ans=dfs(n);
//System.out.print("Case #"+c+": ");
System.out.printf("Case %d: %.10f",c,ans);
System.out.println();
}
}
static double dfs(int n) {
if(n==1)return 0;
if(find[n]!=0)return find[n];
double ans=0;
int g=0,p=0;
for(int i=0;i<l&&primer[i]<=n;i++) {
p++;
if(n%primer[i]==0) {
g++;
ans+=dfs(n/primer[i]);
}
}
//System.out.println(n+" "+g);
find[n]=(ans+p)/g;
return find[n];
}
public static double getDouble() throws Exception {
in.nextToken();
return in.nval;
}
public static int getInt() throws Exception{
in.nextToken();
return (int)in.nval;
}
}