1. 程式人生 > >hihocoder 1164 隨機斐波那契 (期望dp)

hihocoder 1164 隨機斐波那契 (期望dp)

其實最簡單的暴力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)就好了。

#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;
}
然後據說題解很牛X,(打表之前)我是絕對不會看出規律來的。O(∩_∩)O哈哈~