(The 2018 ACM-ICPC Chinese Collegiate Programming Contest -- 宁夏) D. Take Your Seat

Duha decided to have a trip to Singapore by plane.

The airplane had nn seats numbered from 11 to nn, and nn passengers including Duha which were also counted from11 to nn.The passenger with number ii held the ticket corresponding to the seat with number ii, and Duha was the number 11 passenger.

All passengers got on the plane in the order of their numbers from 11 to nn.However, before they got on the plane Duha lost his ticket (and Duha was the only passenger who lost the ticket), so he could not take his seat correctly.He decided to take a seat randomly.And after that, while a passenger got on the plane and found that his/her seat has been occupied, he/she selected an empty seat randomly as well.A passenger except Duha selected the seat displayed in his/her ticket if it had not been occupied by someone else.

The first problem you are asked to calculate in this problem is the probability of the last passenger to get on the plane that took his/her correct seat.

Several days later, Duha finished his travel in Singapore, and he had a great time.

On the way back, he lost his ticket again.And at this time, the airplane had mm seats numbered from 11 to mm, and mm passengers including Duha which were also counted from 11 to mm.The passenger with number ii held the ticket corresponding to the seat with number ii, and Duha was the number 11 passenger as well.

The difference was that: all passengers got on the plane in a random order (which was any one of the m!m!different orders with the same chance).Similarly, Duha or a passenger who found his/her seat had been occupied selected an empty seat randomly.

The second problem you are asked to calculate in this problem is the probability of the last passenger to get on the plane that took his/her right seat on the return trip.

Input Format

The input contains several test cases, and the first line is a positive integer TT indicating the number of test cases which is up to 5050.

For each test case, a line contains two integers nn and m~(1\le n, m\le 50)m (1≤n,m≤50).

Output Format

For each test case, output a line containing Case #x: y z, where xx is the test case number starting from 11, yy is the answer of the first problem, and zz is the answer of the second problem.Both of yy and zz are rounded to 66places, and we guarantee that their 77-th places after the decimal point in the precise answer would not be 44 or 55.

样例输入

1
2 3

样例输出

Case #1: 0.500000 0.666667

 解释一下此时的k相当于一开始的1:

这句话的k是说第k个人相当于在剩下人中的第一个人的地位,第k个人选第一个位置等价于第一个人选第一个位置

 

n-k+1== n-(k-1)   也就是删除2~k这些人的位置

 

 1第i个登机  1在n-(i-1)个人中第一个登机,前面登机的人是坐正确位置的,所以没有影响

 

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAXN 10000
//规律题:
/*
   1.递推关系
   2.在递推的基础上小暴力推结果的规律性,如ans=(n+1)/2n
*/
//
int main()
{
    double f[MAXN],g[MAXN];  //f[i]表示有i个人时的概率
    int t,cnt=1;
    int n,m;
    int i,j;
    scanf("%d",&t);
    while(t--)           //利用递推关系可以推出答案,但有时会超时,可通过小暴力推出结果的规律
    {                    //如本题的规律就是 fn=1(n==1) fn=1/2(n>=2)
                         //                 gn=(n+1)/2n
        memset(f,0,sizeof(f));
        memset(g,0,sizeof(g));
        f[1]=1;
        f[2]=0.500000;
        scanf("%d%d",&n,&m);
        for(i=3;i<=n;i++)
        {
            for(j=1;j<=i-1;j++)
            {
                f[i]+=f[j];
            }
            f[i]/=i;
        }
        if(m<=n)
        {
           for(i=1;i<=m;i++)
           {
               for(j=1;j<=i;j++)
              {
                  g[i]+=f[j];
              }
                 g[i]/=i;
            }
        }
        else
        {
            for(i=n+1;i<=m;i++)
            {
               for(j=1;j<=i-1;j++)
               {
                f[i]+=f[j];
               }
               f[i]/=i;
            }
            for(i=1;i<=m;i++)
            {
               for(j=1;j<=i;j++)
               {
                  g[i]+=f[j];
               }
                  g[i]/=i;
            }
        }
        printf("Case #%d: ",cnt++);
        printf("%.6lf %.6lf\n",f[n],g[m]);  //double 本来就是四舍五入的。
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值