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

inputoutput
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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值