题干:
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),且已经排好序。
。
整理公式得
又因为(因为已经排好序了)
。
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 ;
}