LightOJ 1038

题目链接:http://lightoj.com/volume_showproblem.php?problem=1038

题意是:给你一个N (1 ≤ N ≤ 105) 每次N都随机选一个因子d,然后让N=N/d, 求N变成1的次数的期望;

当 N = 2 时 2有两个因子:1,2

E[2] = E[1]/2 + E[2]/2 + 1;因此可以求出E[2];

当N = 8 时 8有4个因子1 2 4 8;

E[8] = E[1]/4 + E[2]/4 + E[4]/4 + E[8]/4+ 1;因此可以求出E[8];

......

我们用 E[i] 表示 i 变成 1 的次数期望;那么E[i] = E[a[1]]/cnt + E[a[2]]/cnt + ... + E[a[cnt]]/cnt + 1;(加1是因为本次除了一次);

其中cnt为 i 的因子个数,a数组为 i 的因子集合,如果按从小到大的顺序排列 则 a[1] = 1, a[cnt] = i;

所以上式中的a[cnt]替换为i;整理可得 E[i] = (E[a[1]]+E[a[2]]+ ... +E[a[cnt-1]]+cnt)/(cnt-1);

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
#define N 100005
#define met(a, b) memset(a, b, sizeof(a))
#define MOD 110119

typedef long long LL;

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];///j是i的因子,i/j也是i的因子;
                }
            }
        }
        sum += cnt;
        dp[i] = sum/(cnt-1);
    }
}

int main()
{
    Init();
    int T, t = 1, n;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        printf("Case %d: %.6f
", t++, dp[n]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5757576.html