期望DP——G - Race to 1 Again LightOJ - 1038

博客目录

一、原题

题目传送门(vjudge有密码)

题目传送门(lightOJ)

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 Dby 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 than10-6 will be ignored.

Sample Input

3

1

2

50

Sample Output

Case 1: 0

Case 2: 2.00

Case 3: 3.0333333333

二、题目大意

给一个正整数n,现在等概率地选择n的一个因数(包括1和n本身,不一定是质数),拿n除以因数得到一个新的n,不断重复此过程直到n变为1。求变为1所需次数的期望。

三、分析

设期望为e=f(n),n的因数为  ai (不包括1) 和 1,因数的个数为cnt,则选取每个因数的概率p=1/cnt,当n为1时f(1)=0

则:

    e=∑(f(n/a1)*p+1)+e*p

      =p*∑f(n)+cnt+e*p

    移项将e移到左边,并化简得

    (1-p)*e=p*∑f(n)

     e=p/(1-p)*∑f(n)=1/(cnt-1)*∑f(n)

方法:记忆化搜索没得说。

考虑好边界条件,当n为质数时f(n)=2,当n为1时f(1)=0

求因数时直接暴力求 ,记得一次求两个,即i从2到sqrt(x)而不是2到x,此处是tle or not的关键。

四、AC代码

#include<bits/stdc++.h>
using namespace std;
int const maxn=1e5+10;
int Mark[maxn]={0};//0表示素数 
int prime[maxn];
int Prime() //素数筛求1e5以内的质数
{
	int index=0;
	int i,j;
	for( i = 2; i<maxn; i++)
	{
		if(Mark[i] == 0)
			prime[index++]=i;
		for(int j=0;j<index && prime[j]*i<maxn;j++)
		{
			Mark[i*prime[j]]=1;
			if(i % prime[j] == 0)
				break;
		}
	}
	Mark[1]=1;
	return index;
}

double lst[maxn];
double dfs(int x)
{
	if(lst[x])
		return lst[x];
	if(x==1)
		return 0;
	if(Mark[x]==0)
	{
		return 2;
	}
	int i;
	int n=2;
	double sum=0;
	for(i=2;i*i<=x;i++)
	{
		if(x%i==0)
		{
			n++;
			sum+=dfs(i);
			if(i*i!=x)
			{
				sum+=dfs(x/i);
				n++;
			}
		}
	}
	sum+=n;
	return lst[x]=sum/(n-1);
}
int main()
{
	int T,n;
	Prime();
	cin>>T; 
	int cs=1;
	while(T--)
	{
		scanf("%d",&n);
		printf("Case %d: %.8f\n",cs++,dfs(n));
	}
	
}


猜你喜欢

转载自blog.csdn.net/greybtfly/article/details/80551499