0
点赞
收藏
分享

微信扫一扫

【LightOJ - 1038】Race to 1 Again(概率dp,数学期望)

千行 2022-06-15 阅读 25

题干:

Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.

In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D. He repeats this procedure until D becomes 1. What is the expected number of moves required for N to become 1.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case begins with an integer N (1 ≤ N ≤ 105).

Output

For each case of input you have to print the case number and the expected value. Errors less than 10-6 will be ignored.

Sample Input

3

1

2

50

Sample Output

Case 1: 0

Case 2: 2.00

Case 3: 3.0333333333

题目大意:

给个数字D,我们可以选择1~D中可以被D整除的因子,除以D得到一个新的D,再用新D除以它的因子得到又一个新D,按次操作除到D=1时结束,求除的次数的期望值。

p[D]表示从D除到1的期望次数,D的因子有cnt个(包括1和本身)

解题报告:

假设dp[n]代表从n开始退化到1的期望次数,p[n]代表n的因子的集合(vector),且已经排好序。

【LightOJ - 1038】Race to 1 Again(概率dp,数学期望)_#include

整理公式得

【LightOJ - 1038】Race to 1 Again(概率dp,数学期望)_i++_02

又因为【LightOJ - 1038】Race to 1 Again(概率dp,数学期望)_i++_03(因为已经排好序了)

【LightOJ - 1038】Race to 1 Again(概率dp,数学期望)_#include_04

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 1e5 + 5;
int n,a[MAX];
double dp[MAX];
vector<int> vv[MAX];
void init() {
for(int i = 1; i<MAX; i++) {
for(int j = 1; j*j<=i; j++) {
if((i%j) != 0) continue;
vv[i].pb(j);
if(j*j!=i) vv[i].pb(i/j);
}
}
}
void init2() {
dp[1]=0;
for(int i = 2; i<MAX; i++) {
int up = vv[i].size();
for(int j = 0; j<up; j++) {
int v = vv[i][j];
if(v == i) continue;
dp[i] += dp[v]/(up-1);
}
dp[i]+=up*1.0/(up-1);
}
}
int main()
{
init();
init2();
int t,iCase=0;
cin>>t;
while(t--) {
scanf("%d",&n);
printf("Case %d: %.8f\n",++iCase,dp[n]);
}
return 0 ;
}

 


举报

相关推荐

0 条评论