2 条题解
-
0
这是一个功能完备的数据生成器代码(C++)。它会生成 1 到 10 号测试点的
.in和.out文件。生成器特点
- 覆盖样例:测试点 1~5 严格对应题目描述中提供的“样例2”、“样例3”、“样例4”以及“附加题”挑战,确保学生能通过题目给出的基础测试。
- 边界覆盖:测试点 6 覆盖了纯色序列(全A、全U等)。
- 规模递增:测试点 7~10 逐渐增加数据量和序列长度,从随机短序列到长序列,用于测试程序的鲁棒性和基本性能。
- 生物学合理性:随机生成的序列长度均为 3 的倍数,模拟真实的密码子结构。
使用方法
- 将代码保存为
gen.cpp。 - 编译并运行:
g++ gen.cpp -o gen && ./gen(Windows 下运行gen.exe)。 - 运行结束后,当前目录下会生成
1.in/1.out到10.in/10.out共 20 个文件。
C++ 数据生成器代码
#include <iostream> #include <fstream> #include <string> #include <vector> #include <random> #include <ctime> #include <algorithm> using namespace std; // ========================================== // 核心逻辑:标准解答 (用于生成 .out 文件) // ========================================== string solve_dna(const string& s) { // 预期输入格式 5XXXXX3 string res = "3"; // 从下标1开始遍历到倒数第2个字符 for (size_t i = 1; i < s.length() - 1; ++i) { char c = s[i]; if (c == 'A') res += 'U'; else if (c == 'U') res += 'A'; else if (c == 'G') res += 'C'; else if (c == 'C') res += 'G'; else res += c; // 容错,理论上不会生成其他字符 } res += "5"; return res; } // ========================================== // 数据生成工具箱 // ========================================== mt19937 rng(time(0)); // 生成指定长度的随机mRNA序列(不含5和3) string rand_seq(int length) { const char bases[] = {'A', 'U', 'C', 'G'}; string s = ""; for (int i = 0; i < length; ++i) { s += bases[rng() % 4]; } return s; } // 封装生成一个测试点的函数 void generate_test_point(int id) { string in_name = to_string(id) + ".in"; string out_name = to_string(id) + ".out"; ofstream fin(in_name); ofstream fout(out_name); vector<string> inputs; // ========================================== // 测试点配置 // ========================================== // 测试点 1: 题目样例 1 (基础) if (id == 1) { inputs.push_back("5AUG3"); } // 测试点 2: 题目样例 2 (基础入门) else if (id == 2) { inputs.push_back("5AUG3"); inputs.push_back("5UUU3"); } // 测试点 3: 题目样例 3 (典型多肽链) else if (id == 3) { inputs.push_back("5AUGCCCGGG3"); inputs.push_back("5GUCAGCCAC3"); inputs.push_back("5UUCAAGUGC3"); } // 测试点 4: 题目样例 4 (易错陷阱题 A/U混合) else if (id == 4) { inputs.push_back("5AUAAUAAUA3"); inputs.push_back("5CGCGCGCGC3"); inputs.push_back("5GAUGAUGAU3"); inputs.push_back("5UGGUGGUGG3"); } // 测试点 5: 题目 "附加题" 挑战 (较长序列) else if (id == 5) { inputs.push_back("5AUGGCCAAGUACGACAAG3"); } // 测试点 6: 纯色序列边界测试 (全A, 全U, 全C, 全G) else if (id == 6) { inputs.push_back("5AAAAAAAAA3"); inputs.push_back("5UUUUUUUUU3"); inputs.push_back("5CCCCCCCCC3"); inputs.push_back("5GGGGGGGGG3"); } // 测试点 7: 随机短序列 (10行,长度30) else if (id == 7) { int n = 10; for(int i=0; i<n; ++i) { inputs.push_back("5" + rand_seq(30) + "3"); } } // 测试点 8: 随机中长序列 (20行,长度90) else if (id == 8) { int n = 20; for(int i=0; i<n; ++i) { inputs.push_back("5" + rand_seq(90) + "3"); } } // 测试点 9: 随机长序列 (50行,长度300) else if (id == 9) { int n = 50; for(int i=0; i<n; ++i) { inputs.push_back("5" + rand_seq(300) + "3"); } } // 测试点 10: 压力测试 (100行,长度1000) // 内存限制1MB,100*1000字符约为100KB,完全在安全范围内 else if (id == 10) { int n = 100; for(int i=0; i<n; ++i) { inputs.push_back("5" + rand_seq(1000) + "3"); } } // ========================================== // 写入文件 // ========================================== fin << inputs.size() << endl; // 先输出 n for (const string& s : inputs) { fin << s << endl; fout << solve_dna(s) << endl; } fin.close(); fout.close(); cout << "Generated Test Point " << id << endl; } int main() { // 生成 1 到 10 号测试点 for (int i = 1; i <= 10; ++i) { generate_test_point(i); } cout << "All data generated successfully." << endl; return 0; }测试点详细说明
- 1.in/out: 对应题目描述的第一个简单样例,只包含
5AUG3。 - 2.in/out: 对应题目文档中的 样例数据 2,包含
5AUG3和5UUU3。 - 3.in/out: 对应题目文档中的 样例数据 3,包含 3 条长度为 9 的多肽链序列。
- 4.in/out: 对应题目文档中的 样例数据 4,测试 A/U 和 C/G 的大量交替。
- 5.in/out: 对应题目文档中的 “附加题”挑战,一条较长的真实编码序列。
- 6.in/out: 边界测试。测试纯 A、纯 U、纯 C、纯 G 的序列,检查程序是否在特定字符上逻辑出错。
- 7.in/out: 小规模随机。10 条数据,每条长度 30(10个密码子)。
- 8.in/out: 中规模随机。20 条数据,每条长度 90(30个密码子)。
- 9.in/out: 大规模随机。50 条数据,每条长度 300(100个密码子)。
- 10.in/out: 压力测试。100 条数据,每条长度 1000。总文件大小约 100KB,符合 1MB 内存限制下的测试需求,同时检查 算法的效率。
-
0
这是一个经典的字符串处理题目,结合了生物学转录翻译的规则。
解题思路
根据题目描述的三大法则,我们可以总结出程序的处理逻辑:
- 输入解析:读取字符串,去掉开头的
5和结尾的3,只保留中间的碱基序列。 - 碱基互补(镜像法则):遍历剩下的碱基序列,进行如下替换:
- 'A' 'U'
- 'U' 'A'
- 'G' 'C'
- 'C' 'G'
- 反向平行(方向法则):
- 输入是 mRNA(5' 3')。
- tRNA 与其反向平行结合。
- 题目要求输出的格式是以
3开头,以5结尾。 - 关键点:由于输入是
5...3,输出要求是3...5,这意味着我们不需要倒序字符串,只需要按位进行碱基互补替换,然后把两端的数字标签改掉即可。例如 mRNA 的第 1 个碱基(5'端)对应 tRNA 的第 1 个碱基(3'端)。
C++ 代码实现
#include <iostream> #include <string> #include <vector> using namespace std; // 获取互补碱基的函数 char get_complement(char c) { switch(c) { case 'A': return 'U'; case 'U': return 'A'; case 'G': return 'C'; case 'C': return 'G'; default: return c; // 防止异常字符 } } void solve() { int n; // 读取测试用例数量 cin >> n; string s; while (n--) { cin >> s; // 题目输入格式固定为 5xxxxxx3 // 我们先输出开头的 3 cout << "3"; // 遍历字符串中间的部分(跳过下标0的'5'和最后一个下标的'3') for (int i = 1; i < s.length() - 1; ++i) { cout << get_complement(s[i]); } // 输出结尾的 5 并换行 cout << "5" << endl; } } int main() { // 优化输入输出效率 ios_base::sync_with_stdio(false); cin.tie(NULL); solve(); return 0; }复杂度分析
- 时间复杂度:,其中 是所有测试用例中字符串长度的总和。我们需要遍历每个字符一次。
- 空间复杂度:(C++版本),除了存储当前行字符串外,不需要额外的复杂数据结构。这完全符合 1MB 的内存限制。
针对样例数据的测试结果
输入:
2 5AUG3 5UUU3逻辑推演:
5AUG3提取AUG互补UAC添加方向3UAC55UUU3提取UUU互补AAA添加方向3AAA5
输出:
3UAC5 3AAA5与题目样例完全一致。
- 输入解析:读取字符串,去掉开头的
- 1
信息
- ID
- 19232
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 1
- 标签
- 递交数
- 10
- 已通过
- 3
- 上传者