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
题意:这道题的话就是,给你一个数,用它的因子去除它,循环重复这个过程,直至这个数变成1,问需要多少次。
思路:看起来问多少次是一个期望问题,但这个不是单纯的期望dp,举个例子,比如50。50的因子为{1,2,5,10,25,50}。显而易见,用因子去除一个数剩下的数还是他的因子,假如现在剩下的数是10,那么问题就转化为了把10变成1需要几次的问题。从这里我们可以看出,50需要的次数(我们记为E(50))取决于1,2,5,10,25,50出现的次数。这就注定了我们的计算顺序是从前往后依次计算的。
假设数X的因子个数是为N,则
f(X) = 1/N * (f(X1) + f(X2) + … +f(X))
由于在此时f(X)在此时是未知的,我们呢就将式子化简一下。
最终化简成 f (X) = 1/(N-1) * (f(X1) + f(X2) + … +f(X(N-1)))
用一个函数在之前将左右的f(x)算好即可。
AC代码:
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include<iomanip>
typedef long long ll;
const int maxx=100010;
const int inf=0x3f3f3f3f;
using namespace std;
double f[maxx];
void solve()
{
f[1]=0;
for(int i=2;i<=100000;i++)
{
int cnt=-1;
double sum=0;
for(int j=1;j<=sqrt(i);j++)
{
if(i%j==0)
{
cnt++;
sum+=f[j]+1;
if(j*j!=i)
{
cnt++;
sum+=f[i/j]+1;
}
}
}
f[i]=sum/cnt;
}
}
int main()
{
int t;
cin>>t;
solve();
for(int i=1;i<=t;i++)
{
int x;
cin>>x;
cout<<"Case"<<" "<<i<<":"<<" "<<fixed<<setprecision(6)<<f[x]<<endl;
}
return 0;
}