概率論之概率dp? 全期望

http://acm.hust.edu.cn/vjudge/problem/20869

見藍書p143

題意:我們都知道,任何一個數都可以分解爲若干個素數的乘積。每次我們隨機選擇一個比當前數小的素數,如果當前數能被該素數整除,則當前數變爲 當前數 / 該素數的值,反之當前數不變。重複隨機選擇,直到當前數變爲1.問隨機選擇次數的期望。

思路:用遞歸的方法(大霧) 可以將當前的函數f(x)  分解。得到f(x) =... 得到關於f(x)的一個自上而下的公式。(注意此處是根據全期望公式和數學期望的線性,不必證明,會用即可)利用記憶化搜索即可

另:記憶化搜索要記得更改dp的值。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <string>
#include <algorithm>
#include <list>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long LL;
double dp[1000005];
bool vis[1000005];
bool isPrime[2000005];
LL primeList[1000005],primeCount = 0;
void primeInit(LL n)
{

    memset(isPrime,true,sizeof(isPrime));//初始化認爲全部是素數
    int m = sqrt(n + 0.5);
    for(int i = 2; i <= m;  i ++)
    {
        if(isPrime[i])//判斷是素數
        {
            for(int j = i * i; j <= n; j += i)
            {

                isPrime[j] = false;
            }
        }
    }
    for(int i = 2; i <= n; i ++)
    {
        if(isPrime[i])
        {

            primeList[primeCount] = i;
            primeCount ++;
        }

    }
}
double dfs(int a)
{
    if(a == 1)
        return 0.0;
    if(vis[a] ==  true)
        return dp[a];
    double ans = 0.0;
    vis[a] = true;
    int p = 0,g = 0;
    while( p < primeCount)
    {
        if(primeList[p] > a)
        {
            break;
        }
        if(a % primeList[p] == 0)
        {
            ans += dfs(a / primeList[p]);
            g ++;
        }
        p ++;
    }
    if(g == 0)
    {
        return 0;
    }

    ans = (ans + p) / g;
    dp[a] = ans;
    return ans;
}
int main()
{
    //freopen("in.txt","r",stdin);
    primeInit(2000000);

    int T;
    scanf("%d",&T);
    for(int t = 1; t <= T; t ++)
    {
        int x;
        scanf("%d",&x);
        memset(vis,false,sizeof(vis));
        memset(dp,0,sizeof(dp));

        double ans =  dfs(x);

        printf("Case %d: %f\n",t,ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章