ZZULI 1906: 小火山的幸运数字

1906: 小火山的幸运数字

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

Submit Status Web 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[n]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值