LightOJ - 1038 Race to 1 Again(期望)
Posted pixel-teee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ - 1038 Race to 1 Again(期望)相关的知识,希望对你有一定的参考价值。
题意:Rimi学到了一个关于整数的知识,就是任何大于1的整数可以被它的任何因子整除。所以,他准备玩这个特性。他选择了一个整数N,每一次,他随机的选择这个整数的因子,并且整除这个数。直到使得这个数变成1。求N到1的期望值。
分析:一个数可以被它的因子整除,那么整除完的新值也是它的因子。我们定义f[i]:i到1的期望值,那么(f[i] = (f[num[1]] + 1 + f[num[2]] + 1 + f[num[3]] + 1 + ... + f[num[n]] + 1) / num,)num[]数组是i的因子数组,我们可以得出num[n] = i,所以我们可以化简如下:
(f[i] * num = f[num[1]] + f[num[2]] + f[num[3]] + ... + f[num[n]] + num)
(f[i] * (num - 1) = f[num[1]] + f[num[2]] + f[num[3]] + ... + num)
(f[i] = frac{f[num[1]] + f[num[2]] + f[num[3]] + ...}{num - 1})
这道题的数N很大,不能使用记忆化搜索,因为记忆化搜索不能把所有的状态搜到,所以要预处理出所有的值。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 100005;
double f[N];
vector<int> v[N];
int main()
{
int t;
scanf("%d", &t);
//预处理出所有因子
for(int i = 2; i < N; ++i)
for(int j = 1; j <= i / j; ++j)
{
if(i % j == 0)
{
v[i].push_back(j);
if(j * j != i) v[i].push_back(i / j);
}
}
for(int i = 2; i < N; ++i)
{
int sz = v[i].size();
for(int j = 0; j < sz; ++j)
{
if(v[i][j] != i) f[i] += f[v[i][j]];
}
f[i] = (f[i] + sz) / (sz - 1);
}
int c = 0;
while(t--)
{
int n;
scanf("%d", &n);
printf("Case %d: %.6lf
", ++c, f[n]);
}
return 0;
}
以上是关于LightOJ - 1038 Race to 1 Again(期望)的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ 1038 Race To 1 Again(概率DP)
LightOJ - 1038 Race to 1 Again(期望)
LightOJ 1038 - Race to 1 Again (给一个数,用这个数的因数除以这个数,直到为1时,求除的次数的期望。)(概率)