题目大意:对于一个数D,随机地选取D的一个约数X,令D = D / X ,重复上述过程,求将D变为1时,操作次数的期望值。
解题思路:令E[n] 表示数 n 的期望,a[i] 表示 n 的约数, M表示n 的约数的总数,则有 E[n] = ( E[ a[1] ] + 1 ) / M + ( E[ a[2] ] + 1 ) / M + …… + ( E[ a[M] ] + 1 ) / M,而 a[M] = n ,故整理可得:(M - 1) * E[n] = ( E[ a[1] ] + E[ a[2] ] + …… + E[ a[M-1] ] + M 。
代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define N 100005
double dp[N];
void init()
{
dp[1] = 0;
for(int i = 2; i <= N ; i++)
{
double sum = 0;
int cnt = 0;
for(int j = 1; j * j <= i; j ++)
{
if(i % j == 0)
{
cnt ++;
sum += dp[j];
if(j * j != i)
{
cnt ++;
sum += dp[i/j];
}
}
}
dp[i] = (sum + cnt)*1.0 / (cnt - 1);
}
}
int main()
{
int t, n;
init();
scanf("%d", &t);
for(int i = 1; i <= t; i ++)
{
scanf("%d", &n);
printf("Case %d: %.10lf\n", i, dp[n]);
}
return 0;
}