baidu_ACM_Fir

Problem Description

小H是一个程序员。但是他很喜欢一些新奇的东西。

有一次,他去找物理实验室的朋友玩。他见到了一串非常有意思的粒子。N个粒子排成一排。每一秒中,每一段连续的粒子中会随意有一个爆炸,爆炸后该粒子就消失了,且将原来连续的一段粒子分隔成两段。

小H希望知道所有粒子都爆炸完的期望时间。

Input

         第一行为一个整数T(1 <= T<= 400),表示有T组测试数据;

         每组数据一个正整数N(1<=N<=400),表示一开始的粒子数。

Output

         对于每组数据,输出期望时间(秒)。保留五位小数。

Sample Input
3
1
2
3
 
Sample Output
1.00000
2.00000
2.66667
 
Sample Cl.
对N=3,若第一个爆炸的粒子在旁边,则还需两秒;若第一个爆炸的在中间,则再过一秒即可。故答案为2/3*3+1/3*2=8/3。
 
Code
 
View Code
 1 #include <stdio.h>
 2 #include <math.h>
 3 #define N 400
 4 double map[N + 5];
 5 void initilizing()
 6 {
 7     int i, j, n;
 8     map[0] = 0;
 9     map[1] = 1;
10     map[2] = 2;
11     double temp;
12     for (n = 3; n <= N; n++)
13     {
14         temp = 0;
15         if (n % 2 == 0) //偶数
16         {
17             for (j = n / 2; j < n; j++)
18                 temp += map[j];
19             map[n] = 1 + temp * 2 / n;
20         }
21         else
22         {
23             for (j = (n + 1) / 2; j < n ; j++)
24                 temp += map[j];
25             map[n] = 1.0 * (n - 1) / n + temp * 2 / n + (1 + map[(n - 1) / 2]) / n;
26         }
27     }
28 }
29 int main()
30 {
31     int t, num, count, max, i, j, k;
32     double a, b;
33     scanf("%d", &t);
34     initilizing();
35     while (t--)
36     {
37         scanf("%d", &num);
38         printf("%.6f\n", map[num]);
39     }
40     return 0;
41 }

 idea

firstly, we should get the form, then according the form and input, gain the result.

f(1) = 1;

f(2) = 2;

f(3) = 2/3 * (1 + f(2)) + 1/3 * (1 + f(1))

f(4) = 2/4 * (1 + f(3)) + 2/4 * (1 + f(2))

f(5) = 2/5 * (1 + f(4)) + 2/5 * (1 + f(3)) + 1/5 * (1 + f(2))

then u  can get the recursion formula

when n is even number

f(n) = 2/n * (n/2 + f(n-1) + f(n-2) + ... + f(n/2))

when n is odd number

f(n) = 2/n * ((n - 1) / 2 + f(n - 1) + f(n - 2) + ... + f((n - 1) / 2)) + 1/n * (1 + f((n - 1) / 2))

原文地址:https://www.cnblogs.com/chuanlong/p/3048730.html