Light OJ 1038 - Race to 1 Again(概率DP)
题目的意思是说任何一个大于1的整数,经过若干次除以自己的因子之后可以变为1, 求该变换字数的数学期望值。
题目分析:
我们设置dp[n] 为数字n的期望。假设n的因子为k1, k2, k3.... 共有k个
那么 dp[n] = (dp[k1] + dp[k2] +..... + dp[n] + k)* (1/k)
公式化简一下:
dp[n] = (1/(k-1)) * (dp[k1] + dp[k2] .........+dp[n] + k)
式子出来记忆化搜索一下
===========================================================================================
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; const int INF = 1e9+7; const int MAXN = 100055; double dp[MAXN]; double DFS(int n) { if(dp[n] != -1) return dp[n]; dp[n] = 0; int len = sqrt(n+1), k = 0; for(int i=1; i<=len; i++) { if(i*i == n) { k ++; dp[n] += DFS(i); } else if(n%i == 0) { k += 2; dp[n] += DFS(i); dp[n] += DFS(n/i); } } dp[n] = 1.0/(k-1) * (dp[n] + k); return dp[n]; } int main() { int T, cas = 1, n; for(int i=0; i<= 100005; i++) dp[i] = -1; dp[1] = 0; scanf("%d", &T); while(T --) { scanf("%d", &n); printf("Case %d: %.6lf\n",cas ++, DFS(n) ); } return 0; }