LightOJ 1038 Race to 1 Again

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


题意:给一个数n,每次等概率选择它的一个因子p,然后得到n/p,求变为1时的期望次数。

思路:f[i]表示从i变为1的期望次数,f[i] = 1/t ( ∑f[j] ) + 1 ( j是i的因数 )化简一下,得到 f[i] =  ( ( ∑f[j] ) + t ) / ( t-1 ) //t为所有的因子个数,包括1和本身  j为i的真因子。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define Clean(x,y) memset(x,y,sizeof(x))

const int maxn = 100009;

double f[maxn];
bool flag[maxn];
int p[maxn][10];

int n,T;

void getfactor(int x)
{
    p[x][0] = 0;
    for( int i = 2; i * i <= x; i++ )
    {
        if ( x % i == 0 )
        {
            p[x][ ++p[x][0] ] = i;
            if ( i * i != x )
            p[x][ ++p[x][0] ] = x / i;
        }
    }
}

double cal( int x )
{
    if ( flag[x] ) return f[x];
    flag[x] = true;
    getfactor(x);
    double ans = 0;
    for(int i = 1; i <= p[x][0]; i++) ans+=cal( x / p[x][i] );
    return f[x] = ( ans + p[x][0] + 2 ) / ( p[x][0] + 1 );
}

int main()
{
    Clean(flag,false);
    f[0] = f[1] = 0;
    flag[0] = flag[1] = true;
    Clean(p,0);
    scanf("%d",&T);
    int k = 0;
    while(T--)
    {
        k++;
        scanf("%d",&n);
        printf("Case %d: %.10f\n",k,cal(n));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值