题解:洛谷 P2719 搞笑世界杯

【题目来源】

洛谷:P2719 搞笑世界杯 - 洛谷

【题目描述】

随着世界杯小组赛的结束,法国、阿根廷等世界强队都纷纷被淘汰,让人心痛不已。于是有人组织了一场搞笑世界杯,将这些被淘汰的强队重新组织起来和世界杯一同比赛。你和你的朋友欣然去购买球票。不过搞笑世界杯的球票出售方式也很特别,它们只准备了两种球票。

  • A 类票——免费球票。
  • B 类票——双倍价钱球票。

购买时由工作人员通过掷硬币决定,投到正面的买 A 类票,反面的买 B 类票。主办方总是准备了同样多的 A 类票和 B 类票。你和你的朋友十分幸运的排到了某场精彩比赛的最后两个位置。

这时工作人员开始通过硬币售票。不过更为幸运的是当工作人员到你们面前时他发现已无需再掷硬币了,因为剩下的这两张票全是免费票。

你和你的朋友在欣喜之余,想计算一下排在队尾的两个人同时拿到一种票的概率是多少(包括同时拿 A 类票或 B 类票)假设工作人员准备了 \(2n\) 张球票,其中 \(n\) 张 A 类票、\(n\) 张 B 类票,并且排在队伍中的人每人必须且只能买一张球票(不管掷到的是该买 A 还是该买 B)。

【输入】

输入只有一行一个整数,表示 \(2n\)

【输出】

输出只包含一行一个浮点数,为拿到同一种票的概率,精确到小数点后 4 位。

【输入样例】

256

【输出样例】

0.9500

【解题思路】

image

【算法标签】

《洛谷 P2719 搞笑世界杯》 #动态规划DP# #数学# #概率论#

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 1300;
int n;
double f[N*2][N], ans;  // f[i][j]表示前i场比赛,A类票卖出j张的概率

int main()
{
    cin >> n;  // 输入票数的一半,总票数为2n
    n /= 2;  // 将输入转换为n,表示每种票的数量
  
    // 初始化:第一张票
    f[1][1] = 0.5;  // 第一张票是A类票的概率
    f[1][0] = 0.5;  // 第一张票是B类票的概率
  
    // 动态规划
    for (int i=1; i<2*n; i++)  // 遍历已售出的票数,最多售出2n-1张
    {
        for (int j=0; j<=i; j++)  // 遍历A类票已售出的数量
        {
            // 如果A类票已售完(卖出n张),则下一张必须是B类票
            if (j >= n)
            {
                f[i+1][j] += f[i][j];  // 概率转移到下一状态
                continue;
            }
          
            // 如果B类票已售完(即A类票卖出i-j张>=n),则下一张必须是A类票
            if (i-j >= n)  // 等价于A类票还剩n-(i-j)张>0
            {
                f[i+1][j+1] += f[i][j];  // 概率转移到下一状态
                continue;
            }
          
            // 如果两类票都还有剩余,下一张票是A或B的概率各为0.5
            f[i+1][j] += 0.5 * f[i][j];  // 下一张是B类票
            f[i+1][j+1] += 0.5 * f[i][j];  // 下一张是A类票
        }
    }
  
    // 计算最后两张票是相同类型的概率
    // 当剩下最后两张票时,即已售出2n-2张票
    // 要使最后两张票类型相同,有两种情况:
    // 1. 前2n-2张票中,A类票卖了n张,B类票卖了n-2张
    // 2. 前2n-2张票中,A类票卖了n-2张,B类票卖了n张
    // 这两种情况下,最后两张票必须是同类型的
    ans = f[2*n-2][n] + f[2*n-2][n-2];
  
    printf("%.4lf", ans);  // 输出概率,保留4位小数
    return 0;
}

【运行结果】

256
0.9500
posted @ 2026-02-20 20:38  团爸讲算法  阅读(6)  评论(0)    收藏  举报