ACM-ICPC 2017 Asia Urumqi A. Coins

Alice and Bob are playing a simple game. They line up a row of n identical coins, all with the heads facing down onto the table and the tails upward.

For exactly mm times they select any k of the coins and toss them into the air, replacing each of them either heads-up or heads-down with the same possibility. Their purpose is to gain as many coins heads-up as they can.

Input

The input has several test cases and the first line contains the integer t(1t1000) which is the total number of cases.

For each case, a line contains three space-separated integers nm1n,m100) and k (1kn).

Output

For each test case, output the expected number of coins heads-up which you could have at the end under the optimal strategy, as a real number with the precision of 33 digits.

样例输入

6
2 1 1
2 3 1
5 4 3
6 2 3
6 100 1
6 100 2

样例输出

0.500
1.250
3.479
3.000
5.500
5.000

题目来源

ACM-ICPC 2017 Asia Urumqi

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <queue>
 7 #include <set>
 8 #include <map>
 9 #include <string>
10 #include <cmath>
11 #include <cstdlib>
12 #include <ctime>
13 using namespace std;
14 typedef long long ll;
15 int t,n,m,k;
16 const int N=110;
17 double dp[N][N];
18 double    c[N][N];//ll也会爆
19 double p[N];
20 double ans;
21 void C()
22 {
23     c[0][0]=1;
24     for(int i=1;i<=100;i++)
25     {
26         for(int j=0;j<=i;j++)
27         {
28             if(j==0||j==i) c[i][j]=1;
29             else {
30                 c[i][j]=c[i-1][j-1]+c[i-1][j];
31             }
32         }
33     }
34     p[0]=1;
35     for(int i=1;i<=100;i++) p[i]=p[i-1]/2;
36 }
37 int main()
38 {
39     scanf("%d",&t);
40     C();
41     /*
42     for(int i=1;i<=100;i++)
43     {   printf("%dllll\n",i);
44         for(int j=0;j<=i;j++)
45         {
46             printf("%d%c",c[i][j],j==i?'\n':' ');
47         }
48         //c[33][j]就爆int 了。
49     }
50     */
51     while(t--)
52     {
53         scanf("%d%d%d",&n,&m,&k);
54         memset(dp,0,sizeof(dp));
55         //dp[i][j]: i次操作后,正面朝上的面数为j的概率
56         dp[0][0]=1;//初始都是反面
57         for(int i=0;i<m;i++)
58         {
59             for(int j=0;j<=n;j++)
60             {
61                for(int l=0;l<=k;l++)//取得k个里面l个正面朝上。
62                {   //反面的个数大于k,直接从反面的里面取k个
63                    if((n-j)>=k)  dp[i+1][j+l]+=dp[i][j]*c[k][l]*p[k];
64                    //反面的个数小于k,只能再从已经是正面的里面再取出k-(n-j)个。
65                    else  dp[i+1][j-(k-(n-j))+l]+=dp[i][j]*c[k][l]*p[k];
66                }
67             }
68         }
69         ans=0;
70         for(int i=1;i<=n;i++)ans+=i*dp[m][i];//期望
71         printf("%.3f\n",ans);
72     }
73     return  0;
74 }

猜你喜欢

转载自www.cnblogs.com/tingtin/p/9397610.html