题干:
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代码:
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 ;
}