题目链接:http://lightoj.com/volume_showproblem.php?problem=1038
题意是:给你一个N (1 ≤ N ≤ 105) 每次N都随机选一个因子d,然后让N=N/d, 求N变成1的次数的期望;
当 N = 2 时 2有两个因子:1,2
E[2] = E[1]/2 + E[2]/2 + 1;因此可以求出E[2];
当N = 8 时 8有4个因子1 2 4 8;
E[8] = E[1]/4 + E[2]/4 + E[4]/4 + E[8]/4+ 1;因此可以求出E[8];
......
我们用 E[i] 表示 i 变成 1 的次数期望;那么E[i] = E[a[1]]/cnt + E[a[2]]/cnt + ... + E[a[cnt]]/cnt + 1;(加1是因为本次除了一次);
其中cnt为 i 的因子个数,a数组为 i 的因子集合,如果按从小到大的顺序排列 则 a[1] = 1, a[cnt] = i;
所以上式中的a[cnt]替换为i;整理可得 E[i] = (E[a[1]]+E[a[2]]+ ... +E[a[cnt-1]]+cnt)/(cnt-1);
#include <cstring> #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> using namespace std; #define N 100005 #define met(a, b) memset(a, b, sizeof(a)) #define MOD 110119 typedef long long LL; double dp[N]; void Init() { dp[1] = 0; for(int i=2; i<N; i++) { double sum = 0; int cnt = 0; for(int j=1; j*j<=i; j++) { if( i%j == 0 ) { cnt++; sum += dp[j]; if(j*j != i) { cnt ++; sum += dp[i/j];///j是i的因子,i/j也是i的因子; } } } sum += cnt; dp[i] = sum/(cnt-1); } } int main() { Init(); int T, t = 1, n; scanf("%d", &T); while(T--) { scanf("%d", &n); printf("Case %d: %.6f\n", t++, dp[n]); } return 0; }
时间: 2024-10-10 14:51:14