ZZULI 1906: 小火山的幸运数字

来源:互联网 发布:足球阵容设计软件 编辑:程序博客网 时间:2024/05/16 01:09

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的期望 平均需要多少次变成1int 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[n]);    }    return 0;}


0 0