ural - 1776 Anniversary Firework

題目:http://acm.timus.ru/problem.aspx?space=1&num=1776

Denis has to prepare the Ural State University 90th anniversary firework. He bought n rockets and started to think of the way he should launch them. After a pair of sleepless nights he invented the following algorithm.

All n rockets are placed on the surface in a single line. The interval between two consecutive salvos is ten seconds. The leftmost and the rightmost rocket are launched in the first salvo. After i salvos are fired, all non-empty segments between two neighboring launched rockets are considered. One rocket is chosen randomly and uniformly at each of these segments. All chosen rockets are launched in the (i + 1)-st salvo. Algorithm runs until all rockets are launched.

Calculate the average duration in seconds of such a firework.

Input

The only input line contains an integer n (3 ≤ n ≤ 400), which is the number of rockets bought by Denis.

Output

Output the expected duration of the firework in seconds, with absolute or relative error not exceeding 10−6.

Sample

input output
5
26.66666666666

Notes

First, the rockets with numbers 1 and 5 are launched. 10 seconds later the rocket 3 is launched with probability 1/3; in that case, 10 more seconds later the rockets 2 and 4 are launched, and the firework is over after 20 seconds. In case the rocket 2 or rocket 4 is launched in the second salvo (this happens with probability 2/3), the firework is over after 30 seconds.

思路:
概率dp。

dp[i][j]表示點燃i個火箭需要j個10秒時間的概率。

sum[i][j]表示點燃i個火箭需要小於等於j個10秒時間的概率。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 450;

double dp[MAXN][MAXN];
double sum[MAXN][MAXN];
 
int main()
{
    int n;
 
    while (scanf("%d", &n) != EOF)
    {
        n -= 2;
        memset(dp, 0, sizeof(dp));
        memset(sum, 0, sizeof(sum));
 
        dp[0][0] = 1.0;
        for (int i = 0; i <= n; i++)
	    {
            sum[0][i] = 1.0;
	    }

        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= i; j++) 
            {
                int l = j - 1;
			    int r = i - j;  
 
                int temp = max(l, r) + 1;
                for (int k = 1; k <= temp; k++)
                { 
                    dp[i][k] += (dp[l][k-1] * sum[r][k-1] + sum[l][k-1] * dp[r][k-1]
                                - dp[l][k-1] * dp[r][k-1]) / i;
                } 
            }

            for (int j = 1; j <= n; j++)
		    {
                sum[i][j] = sum[i][j-1] + dp[i][j];
		    }
        }
        double ans=0;
        for (int i = 1; i <= n; i++)
	    {
            ans += dp[n][i] * i;
	    }

        printf("%.10lf\n", ans * 10.0);
    }

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章