UVA - 11762 - Race to 1 记忆化概率

Dilu have learned a new thing about integers, which is - any positive integer greater than 1 can be
divided by at least one prime number less than or equal to that number. 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 prime number less than or equal to D. If D is divisible by the
prime number then he divides D by the prime number to obtain new D. Otherwise he keeps the old
D. He repeats this procedure until D becomes 1. What is the expected number of moves required for
N to become 1.
[We say that an integer is said to be prime if its divisible by exactly two different integers. So, 1 is not
a prime, by definition. List of first few primes are 2, 3, 5, 7, 11, ...]
Input
Input will start with an integer T (T ≤ 1000), which indicates the number of test cases. Each of the
next T lines will contain one integer N (1 ≤ N ≤ 1000000).
Output
For each test case output a single line giving the case number followed by the expected number of turn
required. Errors up to 1e-6 will be accepted.
Sample Input
3
1
3
13
Sample Output
Case 1: 0.0000000000
Case 2: 2.0000000000
Case 3: 6.0000000000

 

题意:给出一个整数N,每次可以在不超过N的素数中随机选择一个P,如果P是N的约数,则把N变成N/P,否则N不变。问平均情况下需要多少次选择,才能把N变成1.

题解:记录dp[n] 表示 N = n是答案是多少

   dp[n] = 1 +  ∑dp[素数因子] *  1/素数总和  +   ∑dp[x] * (x为非因子素数)/ 素数总和

      记忆化爆搜就可以

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std ;
typedef long long ll;

const int N=1000000;

int H[N + 5],P[N],cnt,vis[N + 5];
double dp[N + 6];
void prime_table() {
    H[1] = 1;
    for(int i = 2 ; i <= N ; i++) {
        if(!H[i]) {
            P[++cnt] = i;
            for(int j = 2 * i ; j <= N ; j += i) H[j] = 1;
        }
    }
}
double dfs(int n) {
    if(vis[n]) return dp[n];
    if(n == 1) return dp[n] = 0;
    double& ans = dp[n];
    int sum = 0, g = 0;
    vis[n] = 1;
    for(int i = 1 ; i <= cnt && P[i] <= n; i++) {
        sum ++;
        if(n % P[i] == 0) {
            ans += dfs(n / P[i]);
        }else g++;
    }
    return ans = (ans + sum) / (sum - g);
}
int main () {
    cnt = 0;
    prime_table();
    int T, cas = 1, n;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        dfs(n);
        printf("Case %d: %.10f\n", cas++, dp[n]);
    }
    return 0;
}
代码

 

posted @ 2016-01-11 22:32  meekyan  阅读(314)  评论(0编辑  收藏  举报