HDU 5194 DZY Loves Balls

Problem Description
There are  n  black balls and  m  white balls in the big box.

Now, DZY starts to randomly pick out the balls one by one. It forms a sequence  S . If at the  i -th operation, DZY takes out the black ball,  Si=1 , otherwise  Si=0 .

DZY wants to know the expected times that '01' occurs in  S .
 

Input
The input consists several test cases. ( TestCase150 )

The first line contains two integers,  n m(1n,m12)
 

Output
For each case, output the corresponding result, the format is  p/q ( p  and  q  are coprime)
 

Sample Input
   
   
   
   
1 1 2 3
 

Sample Output
   
   
   
   
1/2 6/5
Hint
Case 1: S='01' or S='10', so the expected times = 1/2 = 1/2 Case 2: S='00011' or S='00101' or S='00110' or S='01001' or S='01010' or S='01100' or S='10001' or S='10010' or S='10100' or S='11000', so the expected times = (1+2+1+2+2+1+1+1+1+0)/10 = 12/10 = 6/5

考虑期望的可加性。第
      
       i(1i<n+m)
      个位置上出现0,第
      
       i+1
      个位置上出现1的概率是
      
       mn+m×nn+m1
      ,那么答案自然就是
      
       i=1n+m1mn+m×nn+m1=nmn+m
      
如果你不能马上想到上述的简便的方法,也可以选择暴力枚举所有01串,也是可以AC的。最后一步你需要再计算一下gcd,十分简便。
强大的题解,可惜本人是想不到这样的,自己dp玩玩。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
using namespace std;
const int maxn = 20;
int n, m, T, f[maxn][maxn][4], tot;

int gcd(int x, int y)
{
    if (x % y != 0) return gcd(y, x%y);
    return y;
}

int main()
{
    while (scanf("%d%d", &n, &m) != EOF)
    {
        memset(f, 0, sizeof(f));
        for (int i = 1; i <= max(n, m); i++) f[0][i][0] = f[i][0][1] = 1;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                if (i + j)
                {
                    f[i][j][0] = f[i][j - 1][0] + f[i][j - 1][1];
                    f[i][j][2] = f[i][j - 1][2] + f[i][j - 1][3];
                    f[i][j][1] = f[i - 1][j][0] + f[i - 1][j][1];
                    f[i][j][3] = f[i - 1][j][2] + f[i - 1][j][3] + f[i - 1][j][0];
                }
        for (int i = n + 1, j = tot = 1; i <= n + m; i++)
        {
            tot *= i;
            while (j <= m&&tot%j == 0) tot = tot / j++;
        }
        int k = gcd(tot, f[n][m][3] + f[n][m][2]);
        printf("%d/%d\n", (f[n][m][2] + f[n][m][3]) / k, tot / k);
    }
}


你可能感兴趣的:(dp,HDU,gcd)