2 条题解
-
0
你好,我是阿西莫夫。
为了确保你的测试数据既符合科学逻辑,又能经受住评测系统的考验(特别是防止概率下溢变成全零),我为你专门编写了这套带“保底机制”的数据生成器。
这个生成器会自动生成
1.in~10.in以及对应的标准答案1.out~10.out。C++ 数据生成器 (gen_mendel.cpp)
请将以下代码保存并运行。它包含了标准解答逻辑和输入生成逻辑。
/** * Project: Mendel's Garden (Data Generator) * Author: Isaac Asimov (AI) * Features: * 1. Integrates the standard solution to generate .out files. * 2. Outputs probabilities with 2 decimal precision. * 3. Includes "Easy Mode" for large N to prevent probability underflow (0.00). */ #include <iostream> #include <fstream> #include <random> #include <string> #include <vector> #include <iomanip> #include <cctype> using namespace std; // ========================================== // Part 1: 标准解答逻辑 (The Ground Truth) // ========================================== class Solution { // 判断是否表现为显性 bool is_dominant(char g1, char g2) { return (g1 >= 'A' && g1 <= 'Z') || (g2 >= 'A' && g2 <= 'Z'); } public: void solve(string in_file, string out_file) { ifstream cin(in_file); ofstream cout(out_file); if (!cin.is_open()) return; int n; if (!(cin >> n)) return; string s1, s2, t; cin >> s1 >> s2 >> t; double total_prob = 1.0; for (int i = 0; i < n; i++) { char p1a = s1[2 * i]; char p1b = s1[2 * i + 1]; char p2a = s2[2 * i]; char p2b = s2[2 * i + 1]; // 目标是否要求显性 bool want_dominant = (t[i] >= 'A' && t[i] <= 'Z'); int match_count = 0; // 孟德尔棋盘 2x2 枚举 if (is_dominant(p1a, p2a) == want_dominant) match_count++; if (is_dominant(p1a, p2b) == want_dominant) match_count++; if (is_dominant(p1b, p2a) == want_dominant) match_count++; if (is_dominant(p1b, p2b) == want_dominant) match_count++; total_prob *= (match_count / 4.0); } // 核心要求:保留 2 位小数 cout << fixed << setprecision(2) << total_prob << endl; cin.close(); cout.close(); cout << "Generated: " << out_file << endl; } }; // ========================================== // Part 2: 数据生成逻辑 // ========================================== mt19937 rng(2025); int rand_int(int min, int max) { uniform_int_distribution<int> dist(min, max); return dist(rng); } // 辅助函数:生成一对等位基因字符串 // type: 0=隐性纯合(aa), 1=杂合(Aa), 2=显性纯合(AA) // base: 基础字符,如 'A' string gen_gene_pair(int type, char base) { string res = ""; char upper = toupper(base); char lower = tolower(base); if (type == 0) { // aa res += lower; res += lower; } else if (type == 2) { // AA res += upper; res += upper; } else { // Aa (随机顺序 Aa 或 aA) if (rand_int(0, 1)) { res += upper; res += lower; } else { res += lower; res += upper; } } return res; } void generate_input(int case_id) { string filename = to_string(case_id) + ".in"; ofstream fout(filename); int n; string s1 = "", s2 = "", t = ""; // --- 规模设定 --- if (case_id == 1) n = 1; // 基础 else if (case_id == 2) n = 2; // 自由组合 else if (case_id == 3) n = 3; else if (case_id <= 7) n = rand_int(5, 15); // 中等规模 else n = rand_int(20, 50); // 大规模 (压力测试) // --- 基因生成循环 --- for (int i = 0; i < n; i++) { char base = 'A' + (i % 26); // 使用 A, B, C... 循环 // --- 策略:防止概率下溢 (Underflow Protection) --- // 当 N 很大时,如果每对基因的概率都是 0.75 或 0.5, // 总概率会迅速变成 0.00000... // 为了让测试数据更有趣,我们在 N 较大时,强制让大部分组合变成“必定事件”(概率1.0) bool force_certainty = false; if (n > 10) { // 70% 的概率生成“必定事件”,保持总分不掉落 if (rand_int(1, 100) <= 70) force_certainty = true; } int type1, type2; char target; if (force_certainty) { // 构造必定事件: AA x AA -> 显性 (100%) type1 = 2; // AA type2 = 2; // AA target = toupper(base); // 目标: 显性 } else { // 完全随机 type1 = rand_int(0, 2); // 0, 1, 2 type2 = rand_int(0, 2); // 随机目标 if (rand_int(0, 1)) target = toupper(base); else target = tolower(base); } s1 += gen_gene_pair(type1, base); s2 += gen_gene_pair(type2, base); t += target; } fout << n << endl; fout << s1 << endl; fout << s2 << endl; fout << t << endl; fout.close(); } int main() { // 提升控制台输出速度 ios_base::sync_with_stdio(false); cout << "--- Generating Mendel's Garden Data ---" << endl; cout << "Target: 2 decimal precision output." << endl; Solution solver; for (int i = 1; i <= 10; i++) { generate_input(i); string in = to_string(i) + ".in"; string out = to_string(i) + ".out"; solver.solve(in, out); } cout << "--- Done! Generated 10 sets of data. ---" << endl; return 0; }重点设计说明
-
防止全零结果 (
force_certainty):- 在遗传学概率计算中,如果 ,即使每项概率高达 ,总概率 ,四舍五入保留两位小数后就是
0.01甚至0.00。 - 为了避免后几个测试点全是
0.00(这样学生只要cout << 0.00就能骗分),我在 的测试点中加入了一个机制:约 70% 的基因对会被生成为 “显性纯合子 x 显性纯合子 目标显性”。 - 这保证了这一项的概率为 ,从而“托住”了总概率,使其可能维持在
0.10~0.90之间,具有区分度。
- 在遗传学概率计算中,如果 ,即使每项概率高达 ,总概率 ,四舍五入保留两位小数后就是
-
严格的格式控制:
- 输入字符串 长度严格为 。
- 目标字符串 长度严格为 。
- 输出严格保留 2 位小数。
这套数据生成器现在完美匹配了我们最终定稿的题目描述。祝你的学生们解题愉快!
-
-
0
#include <iostream> #include <string> #include <vector> #include <iomanip> // 用于保留小数位 using namespace std; // 判断一个基因型(两个字符)表现的是显性还是隐性 // 规则:只要有一个大写字母,就是显性 bool is_dominant_phenotype(char g1, char g2) { bool d1 = (g1 >= 'A' && g1 <= 'Z'); bool d2 = (g2 >= 'A' && g2 <= 'Z'); return d1 || d2; } // 计算单对性状符合目标的概率 double calc_single_prob(char p1_1, char p1_2, char p2_1, char p2_2, char target_type) { // 目标是否要求显性? bool want_dominant = (target_type >= 'A' && target_type <= 'Z'); int match_count = 0; // 枚举 2x2 = 4 种杂交组合 (孟德尔棋盘) if (is_dominant_phenotype(p1_1, p2_1) == want_dominant) match_count++; if (is_dominant_phenotype(p1_1, p2_2) == want_dominant) match_count++; if (is_dominant_phenotype(p1_2, p2_1) == want_dominant) match_count++; if (is_dominant_phenotype(p1_2, p2_2) == want_dominant) match_count++; return (double)match_count / 4.0; } int main() { // IO 优化 ios_base::sync_with_stdio(false); cin.tie(NULL); int n; if (!(cin >> n)) return 0; string s1, s2, t; cin >> s1 >> s2 >> t; double total_prob = 1.0; // 遍历每一对性状 for (int i = 0; i < n; i++) { // 获取第 i 对性状的等位基因 char p1_a = s1[2 * i]; char p1_b = s1[2 * i + 1]; char p2_a = s2[2 * i]; char p2_b = s2[2 * i + 1]; char target = t[i]; // 计算这一对的概率 double p = calc_single_prob(p1_a, p1_b, p2_a, p2_b, target); // 独立事件概率相乘 total_prob *= p; } // 输出保留 2 位小数 cout << fixed << setprecision(2) << total_prob << endl; return 0; }
- 1
信息
- ID
- 19243
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者