1 条题解

  • 0
    @ 2025-4-18 10:59:32

    题意分析

    题目要求:给定一系列音符(如C,D,EC, D, E等),判断这些音符可能属于哪些大调音阶。大调音阶由88个音符组成,其音程间隔为:$全音(2半音)、全音(2半音)、半音(1半音)、全音(2半音)、全音(2半音)、全音(2半音)、半音(1半音)$。例如:

    • CC大调音阶:C,D,E,F,G,A,B,CC, D, E, F, G, A, B, C
    • FF大调音阶:F,G,A,A#,C,D,E,FF, G, A, A\#, C, D, E, F

    解题思路

    1. 输入处理

      • 读取输入的音符序列(如"C C D E"),使用stringstream分割并解析每个音符。
      • 将音符转换为对应的半音阶索引(001111,对应CCBB)。
    2. 生成大调音阶

      • 对于每个可能的调性(共1212种,从CCBB),生成其大调音阶的音符集合:
        • 根据大调音程[0,2,4,5,7,9,11][0, 2, 4, 5, 7, 9, 11],计算每个音符相对于根音的位置(模1212)。
        • 使用布尔数组scale_notes[12]标记属于该音阶的音符。
    3. 检查匹配

      • 对于每个调性,检查输入的所有音符是否都在其音阶集合中。
      • 若全部匹配,则将该调性加入结果列表。
    4. 输出结果

      • 按半音阶顺序(C,C#,D,...,BC, C\#, D, ..., B)输出所有可能的调性,空格分隔。

    关键公式

    • 大调音阶的音程关系:[0,2,4,5,7,9,11][0, 2, 4, 5, 7, 9, 11]
    • 音符索引计算:current=(current+Δ)mod12current = (current + \Delta) \mod 12,其中Δ\Delta为音程序列差值。
    #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
    上传者