ZZULIOJ 2135 这里是天堂!【概率Dp---拆分分子分母】

本题探讨了一个有趣的问题:在一个房间里,通过按按钮让隔壁房间的白猫和黄猫随机来找Maple玩。题目要求计算在给定初始白猫和黄猫数量的情况下,经过若干次操作后,出现特定数量白猫和黄猫的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2135: 这里是天堂!

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 921   Solved: 114

Submit Status Web Board

Description

Maple他打代码打累了,于是Maple跑去找猫猫们来拯救自己。

Maple来到了一个空房间里,房间的隔壁是一个有很多只猫猫的房间,在Maple的房间里有一个按钮,每次按一下按钮,就会有且只有一只猫猫从旁边的房间里跑过来找Maple玩,当然当隔壁房间没有猫的时候并不会有猫猫跑过来。

Maple按了几次按钮后发现跑过来的猫猫只有白色和黄色两种毛色,而且如果假设当每次按按钮后旁边房间剩下的猫跑过来的概率都相同,那么Maple就开始想,如果当隔壁房间共有n只白猫和m只黄猫时,当他按了k次按钮后,跑过来的白猫数量和黄猫数量分别为a只和b只的概率是多少。

 

Input

第一行有一个整数T,代表有T组数据(1<=T<=2000)

每组数据有五个整数n,m,k,a,b,其中0<=n,m,k,a,b<=10

 

Output

对于每组数据,得到的概率为一个分数A/B(A<=B且AB为互质整数),输出两个整数A、B,用一个空格分开。

 

Sample Input

2
1 1 1 1 0
9 1 10 9 1

Sample Output

1  2
1 1

HINT

特殊的,概率为0的分数表示法为0/1。


思路:


如果结果要求输出的是浮点数,那么我们不妨直接设定dp【i】【j】【k】表示按了第i下,已经出来了j只白猫以及k只黄猫的概率。


那么就有:

dp【i】【j】【k】+=dp【i-1】【j-1】【k】*[ (n-j-1) /(n+m-(j-1)-k)];

dp【i】【j】【k】+=dp【i-1】【j】【k-1】*[(m-(k-1))/(n+m-(k-1)-j)];


但是现在要求的是输出分子/分母的形式。

那么我们拓展设定:dp【i】【j】【k】【2】,其中dp【i】【j】【k】【0】存入的是分子,dp【i】【j】【k】【2】存入的是分母即可。

那么过程模拟分数加和并且维护一下分子和分母即可。


注意n==a &&m==b&&k>=n+m的时候也要输出1 1.


另外要注意数据范围。


Ac代码:


#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long int
ll dp[15][15][15][2];
ll gcd(ll x,ll y)
{
    return y==0?x:gcd(y,x%y);
}
int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--)
    {
        ll n,m,k,a,b;
        scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&a,&b);
        if(n==a&&m==b&&k>=a+b)
        {
            printf("1 1\n");
            continue;
        }
        memset(dp,0,sizeof(dp));
        dp[0][0][0][0]=1;
        dp[0][0][0][1]=1;
        for(ll i=1;i<=k;i++)
        {
            for(ll j=0;j<=n;j++)
            {
                for(ll k=0;k<=m;k++)
                {
                    if(j+k==i)
                    {
                         if(j-1>=0)
                         {
                             ll x=dp[i-1][j-1][k][0]*(n-(j-1));
                             ll y=dp[i-1][j-1][k][1]*(n+m-(j-1)-k);
                             ll xx=dp[i][j][k][0];
                             ll yy=dp[i][j][k][1];
                             if(xx==0||yy==0)
                             {
                                ll fenmu=y;
                                ll fenzi=x;
                                ll g=gcd(fenmu,fenzi);
                                fenzi=fenzi/g;
                                fenmu=fenmu/g;
                                dp[i][j][k][0]=fenzi;
                                dp[i][j][k][1]=fenmu;
                             }
                             else
                             {
                                ll fenmu=y*yy;
                                 ll fenzi=x*yy+xx*y;
                                 ll g=gcd(fenmu,fenzi);
                                 fenzi=fenzi/g;
                                 fenmu=fenmu/g;
                                 dp[i][j][k][0]=fenzi;
                                 dp[i][j][k][1]=fenmu;
                             }
                         }
                         if(k-1>=0)
                         {
                             ll x=dp[i-1][j][k-1][0]*(m-(k-1));
                             ll y=dp[i-1][j][k-1][1]*(n+m-(k-1)-j);
                             ll xx=dp[i][j][k][0];
                             ll yy=dp[i][j][k][1];
                             if(xx==0||yy==0)
                             {
                                ll fenmu=y;
                                ll fenzi=x;
                                ll g=gcd(fenmu,fenzi);
                                fenzi=fenzi/g;
                                fenmu=fenmu/g;
                                dp[i][j][k][0]=fenzi;
                                dp[i][j][k][1]=fenmu;
                             }
                             else
                             {
                                ll fenmu=y*yy;
                                 ll fenzi=x*yy+xx*y;
                                 ll g=gcd(fenmu,fenzi);
                                 fenzi=fenzi/g;
                                 fenmu=fenmu/g;
                                 dp[i][j][k][0]=fenzi;
                                 dp[i][j][k][1]=fenmu;
                             }
                         }
                    }
                }
            }
        }
        if(dp[k][a][b][0]==0&&dp[k][a][b][1]==0)printf("0 1\n");
        else
        printf("%lld %lld\n",dp[k][a][b][0],dp[k][a][b][1]);
    }
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值