Given a number D, randomly select an approximate sum of D, then divide d by this rounding, form a new D, continue this step, until d=1,
We ask for the number of times we want to change D to 1.
Set D1,D2...DJ is the d of the line that is divided by the approximate, and Dj==d
Then dp[i] = 1/j*dp[d1] + 1/J*DP[D2]+...+1/J*DP[DJ] + 1
(j-1)/j*dp[i] = 1/j*dp[d1] + 1/j*dp[d2]+...+1/j*dp[dj-1] + 1
So dp[i] = (1/J*DP[D1] + 1/j*dp[d2]+...+1/j*dp[dj-1] + 1) *j/(j-1)
When calculating the DP, we can enumerate its multiples for each number, so that the time complexity is NLOGN
1#include <stdio.h>2#include <string.h>3#include <stdlib.h>4#include <algorithm>5#include <iostream>6#include <queue>7#include <stack>8#include <vector>9#include <map>Ten#include <Set> One#include <string> A#include <math.h> - using namespacestd; - #pragmaWarning (disable:4996) the #pragmaComment (linker, "/stack:1024000000,1024000000") -typedefLong LongLL; - Const intINF =1<< -; - /* + - */ + Const intN =100000+Ten; A DoubleDp[n]; at intCnt[n]; - BOOLVis[n]; - voidInit () - { -dp[1] =0; - for(intDI =2; Di < N; ++DI)//for each Di, enumerate the multiples of it in { -cnt[di]+=2; toDp[di] = (Dp[di]/cnt[di] +1) *cnt[di]/(Cnt[di]-1); + for(inti = di*2; i < N; i + =di) - { thecnt[i]++; *Dp[i] + =Dp[di]; $ }Panax Notoginseng - } the } + intMain () A { the intt, N; +scanf"%d", &t); - init (); $ for(intK =1; K <= T; ++k) $ { -scanf"%d", &n); -printf"Case %d:%.10lf\n", K, Dp[n]); the } - return 0;Wuyi}
View Code
lightoj1038 (expected DP)