写在前面:

牛客每日一题持续更新中!
今天给彦祖和亦菲们带来的是 小天的 Minecraft
题目如下:

1. 题目描述
在游戏里,破坏沙砾会掉落物品,概率分布如下:
铜粒:概率
银粒:概率
金粒:概率
其它:概率
制作铜镐需要:
4 个铜粒 → 1 个铜锭
3 个铜锭 → 1 个铜镐
铜镐只能在 铜工作台 或 银工作台 或 金工作台 上制作
铜工作台:1 个铜锭(4 铜粒)
银工作台:1 个银锭(4 银粒)
金工作台:1 个金锭(4 金粒)
能做出铜镐的条件是以下之一:
铜工作台路线:X≥16(12 铜粒做镐 + 4 铜粒做铜工作台)
银工作台路线:X≥12 且 Y≥4
金工作台路线:X≥12 且 Z≥4
注意:路线 2 和路线 3 可能有重叠(如果 X≥12,Y≥4,Z≥4 则同时满足两个路线),但概率计算时要用容斥原理。
2. 算法描述
设:
A:铜工作台路线事件
B:银工作台路线事件
C:金工作台路线事件
则:
P(A)=P(X≥16)) P(B)=P(X≥12,Y≥4) P(C)=P(X≥12,Z≥4) P(B∩C)=P(X≥12,Y≥4,Z≥4)最终概率:
P=P(A)+P(B)+P(C)−P(B∩C)因为 A与 B,C 互斥(若 X≥16 则 Y=Z=0,不满足 Y≥4 或 Z≥4)。
3. 计算实现
直接枚举所有可能的 (x,y,z) 满足:
x+y+z≤16
且满足上述任一条件
计算多项概率并累加。
已知铜镐需要12个铜粒,而工作台需要4个相同的金属粒
所以 两种情况
第一种是人品爆炸,16个全是铜粒,概率为pow(a/16.0,16)
第二种是拿到12个铜粒,剩下四个银粒或者金粒,
概率为pow(a/16.0,12)*(pow(b/16.0)+pow(c/16.0,4))*
4.代码实现
C/C++版本:
#include <iostream> #include <iomanip> #include <cmath> using namespace std; int main() { int t; // 测试数据组数 cin >> t; // 计算分母:16的16次方,因为每个沙砾有16种可能结果,共16个沙砾 const double denominator = pow(16, 16); for (int i = 0; i < t; i++) { int a, b, c; // 铜粒、银粒、金粒的概率分子(分母固定为16) cin >> a >> b >> c; // 计算分子: // 1. pow(a, 16): 16个沙砾全部掉落铜粒的概率(可以直接制作铜工作台+铜镐) // 2. 1820 * pow(a, 12) * (pow(b, 4) + pow(c, 4)): // - 1820是组合数C(16,4),表示从16个位置中选4个放银粒或金粒 // - pow(a, 12): 12个铜粒的概率 // - pow(b, 4): 4个银粒的概率(制作银工作台) // - pow(c, 4): 4个金粒的概率(制作金工作台) double numerator = pow(a, 16) + 1820 * pow(a, 12) * (pow(b, 4) + pow(c, 4)); // 计算总概率:分子/分母 double P = numerator / denominator; // 输出结果,保留10位小数 cout << fixed << setprecision(10) << P << endl; } return 0; }Python版本:
import math def main(): t = int(input().strip()) # 测试数据组数 # 计算分母:16的16次方 denominator = 16 ** 16 for _ in range(t): a, b, c = map(int, input().split()) # 计算分子: # 1. a**16: 16个沙砾全部掉落铜粒 # 2. 1820 * a**12 * (b**4 + c**4): # - 1820是组合数C(16,4) # - 12个铜粒 + 4个银粒或金粒 numerator = a ** 16 + 1820 * (a ** 12) * (b ** 4 + c ** 4) # 计算概率 P = numerator / denominator # 输出结果,保留10位小数 print(f"{P:.10f}") if __name__ == "__main__": main()Java版本:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int t = scanner.nextInt(); // 测试数据组数 // 计算分母:16的16次方 double denominator = Math.pow(16, 16); for (int i = 0; i < t; i++) { int a = scanner.nextInt(); // 铜粒概率分子 int b = scanner.nextInt(); // 银粒概率分子 int c = scanner.nextInt(); // 金粒概率分子 // 计算分子: // 1. Math.pow(a, 16): 16个沙砾全部掉落铜粒 // 2. 1820 * Math.pow(a, 12) * (Math.pow(b, 4) + Math.pow(c, 4)): // - 1820是组合数C(16,4) // - 12个铜粒 + 4个银粒或金粒 double numerator = Math.pow(a, 16) + 1820 * Math.pow(a, 12) * (Math.pow(b, 4) + Math.pow(c, 4)); // 计算概率 double P = numerator / denominator; // 输出结果,保留10位小数 System.out.printf("%.10f\n", P); } scanner.close(); } }好了,各位码友,代码已经调试通过,文章也已commit,就等各位的push了。点赞不要 //TODO,关注务必 star!
写在后面:



&spm=1001.2101.3001.5002&articleId=155390093&d=1&t=3&u=28775de50b1a41a8b4084022829e2365)
899

被折叠的 条评论
为什么被折叠?



