您的位置:首页 > 其它

ZZULI 1906: 小火山的幸运数字

2016-09-20 22:35 190 查看

1906: 小火山的幸运数字

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 26  Solved: 11

SubmitStatusWeb
Board

Description

  单纯的小火山特别喜欢单纯的事物, 每看到一些东西都想让他们变得单纯起来。
  现在,单纯的小火山开始学数字了, 看到一串串数字, 小火山觉得自己都不单纯了。
小火山只喜欢单纯的数字1,看到其他数字都要强迫性的将他们变成1。小火山改变数字的规则是这样的:
对于一个数字n,通过随机除以n的约数(约数包含1和n),让n变成一个更小的数(包括n)。
  小火山想知道,将这个数字变成1需要变化次数的期望是多少?

Input

输入第一行是一个整数T(T <= 1000), 表示一共有T组数据。
每一组数据,包含一个整数N(1 <= N <= 100000)。

Output

每一组数据输出一个数字,表示N变成1的期望次数, 结果保留两位小数。

Sample Input

3

1

2

50

Sample Output

0.00

2.00

3.03

期望的第一道题  有点懵大神题解

定义f[i] := i变为1的期望次数

设i的约数的个数为c,每个约数为a[i] (i <= 1 <= c)

i每次可以除以任意一个约数,而且每个约数选到的概率为1/c

因此f[i] = segma( 1/c * (f[ i / a[i] ] + 1) )

但当a[i] = 1时,等式右边又会出现f[i],将右边的f[i]移到左边,然后解出f[i]
f[1] = 0,每一个i枚举约数的复杂度O(sqrt(i)),总复杂度O(n * sqrt(n))

我的AC代码

#include "cstdio"
#include "cstring"
#include "algorithm"
#include "cmath"
using namespace std;
int a[100010];
double dp[100010];//代表i的期望 平均需要多少次变成1
int main(){
dp[1]=0;
for(int i=2;i<=100000;i++){
int c=0;
for(int j=1;j<=sqrt(i);j++){
if(i%j==0){
int x=i/j;
if(x!=j){
a[++c]=x; a[++c]=j;
}
else{
a[++c]=j;
}
}
}
// a[++c]=i;
double sum=0; double t=1; double l=1.0/c;
for(int j=1;j<=c;j++){
if(a[j]==1){
t=t-l; sum=sum+l;
}
else
sum=sum+ ( l * (dp[i/a[j]]+1));//选取一个的概率是1/c 然后称期望数+1
}
dp[i]=sum/t;
// printf("%lf %lf %d\n",dp[i],t,c);
}
int T; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n); printf("%.2lf\n",dp
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: