1 条题解
-
0
题意分析
题目要求:给定一系列音符(如等),判断这些音符可能属于哪些大调音阶。大调音阶由个音符组成,其音程间隔为:$全音(2半音)、全音(2半音)、半音(1半音)、全音(2半音)、全音(2半音)、全音(2半音)、半音(1半音)$。例如:
- 大调音阶:
- 大调音阶:
解题思路
-
输入处理:
- 读取输入的音符序列(如
"C C D E"
),使用stringstream
分割并解析每个音符。 - 将音符转换为对应的半音阶索引(到,对应到)。
- 读取输入的音符序列(如
-
生成大调音阶:
- 对于每个可能的调性(共种,从到),生成其大调音阶的音符集合:
- 根据大调音程,计算每个音符相对于根音的位置(模)。
- 使用布尔数组
scale_notes[12]
标记属于该音阶的音符。
- 对于每个可能的调性(共种,从到),生成其大调音阶的音符集合:
-
检查匹配:
- 对于每个调性,检查输入的所有音符是否都在其音阶集合中。
- 若全部匹配,则将该调性加入结果列表。
-
输出结果:
- 按半音阶顺序()输出所有可能的调性,空格分隔。
关键公式
- 大调音阶的音程关系:
- 音符索引计算:,其中为音程序列差值。
#include <iostream> #include <string> #include <vector> #include <sstream> #include <cstring> using namespace std; const char* scale[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; const int major_intervals[7] = {0, 2, 4, 5, 7, 9, 11}; // 大调音阶的音程(相对于根音) int main() { string line; while (getline(cin, line) && line != "END") { // 解析输入的音符 vector<int> notes; istringstream iss(line); string note; while (iss >> note) { for (int i = 0; i < 12; ++i) { if (note == scale[i]) { notes.push_back(i); break; } } } // 检查每个可能的调性 vector<string> possible_keys; for (int key = 0; key < 12; ++key) { bool valid = true; // 生成该调的大调音阶(8个音符) bool scale_notes[12] = {false}; int current = key; for (int i = 0; i < 7; ++i) { scale_notes[current] = true; current = (current + major_intervals[i+1] - major_intervals[i]) % 12; } scale_notes[key] = true; // 包含高八度的根音 // 检查所有音符是否都在这个音阶中 for (int n : notes) { if (!scale_notes[n]) { valid = false; break; } } if (valid) { possible_keys.push_back(scale[key]); } } // 输出结果 for (size_t i = 0; i < possible_keys.size(); ++i) { if (i != 0) cout << " "; cout << possible_keys[i]; } cout << endl; } return 0; }
- 1
信息
- ID
- 1327
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 6
- 已通过
- 1
- 上传者