hihocoder 1164 隨機斐波那契 (期望dp)
阿新 • • 發佈:2019-02-02
其實最簡單的暴力O(n^3)是能過的,,這裡主要是提一下對於大資料時怎麼處理。
對於某個n來說我們要求a_n的期望,考慮一下我們求a_n的時候是隨機從a_n前面的n項中抽出兩項然後相加得到a_n,那麼我們把所有情況分為兩類:第一類是所選的兩個數中有a_(n-1),第二類是所選的數中沒有a_(n-1)。然後分別把兩類的期望求出來相加就好了。
對於第一類的期望:它就是從a_0加到a_(n-1)的和再加上n個a_(n-1)(因為每個數都需要a_(n-1)去跟它配對)然後要乘以第一類的概率就是n/(n*n)=1/n。
對於第二類的期望:我們要知道a_(n-1)是一個期望,期望的意思就相當於我們從前面(n-1)個數中隨便選取兩個數的和是都可以用期望來代替的,那麼我們只要再乘以隨便選取兩個數的概率(n-1)*(n-1)/(n*n)就好了。
然後據說題解很牛X,(打表之前)我是絕對不會看出規律來的。O(∩_∩)O哈哈~#pragma warning(disable:4996) #include <cstdio> using namespace std; double a[505]; int main(){ a[0] = 1; a[1] = 2, a[2] = 3; for (int i = 3; i <= 500; i++){ //這裡我們可以邊迴圈邊處理處sum為前n項和就得到了O(n)的演算法 a[i] = a[i - 1] * (i - 1)*(i - 1); int cnt = i; double sum = 0; for (int j = 0; j < i; j++){ sum += a[j] + a[i - 1]; } sum *= 2; sum -= 2 * a[i - 1]; a[i] += sum; a[i] /= (cnt*cnt); } int n; while (~scanf("%d", &n)){ printf("%.6lf\n", a[n]); } return 0; }