QOJ.ac

QOJ

Límite de tiempo: 1 s Límite de memoria: 32 MB Puntuación total: 10

#11838. 即兴创作 [B]

Estadísticas

Chris 小时候一直想玩爵士乐。他现在长大了,但仍然不会演奏任何乐器。不过,他有一个绝妙的想法,要开发一种新型的即兴演奏系统。更重要的是,Bytelander 教授认为 Chris 的程序——即兴演奏 (Improvisation)——可能是一个不错的博士论文课题!唯一的问题是实现这个算法,这对 Chris 来说太复杂了。

该算法的核心思想是重用现有的即兴演奏来创作新的即兴演奏。每段即兴演奏都有其特定的类型,即适合于固定的和弦序列。即兴演奏算法会对一段适合于某个和弦序列的即兴演奏进行调整,使其在修改后适合于另一个和弦序列。

为了理解该算法,需要一些额外的概念:

首先,有 12 个不同的音符,定义了以下经典顺序:

C, C#(D♭), D, D#(E♭), E, F, F#(G♭), G, G#(A♭), A, A#(B♭), B

B 音符后面是 C(经典顺序是“周期性”的)。标有升号 (#) 的音符也可以标有降号 (♭)。

为了标记即兴演奏中的停顿,还需要停顿的概念。停顿将用 _ 符号标记。

有不同类型的和弦。每个和弦都有一个调式 (mode) 和一个根音 (prime)。根音只是一个单一的音符。共有六种调式:maj7, min7, dim, 7, 7♭9 和 7#9。对于给定的(根音,调式)对,可以定义适合该和弦的音符。为此,我们为每种调式定义其音阶 (scale),即一组 $S \subseteq \{0, 1,\ldots, 11\}$,表示音符相对于根音在经典顺序中的偏移量。例如,如果根音是 D,音阶是 $S = \{0, 2, 4\}$,那么适合的音符集合就是 {D, E, F#}。所有调式的音阶如下:

调式 音阶
maj7 0, 2, 4, 7, 9, 11
min7 0, 2, 3, 5, 7, 9, 10
dim 0, 2, 3, 5, 6, 8, 9, 11
7 0, 2, 4, 7, 9, 10
7♭9 0, 1, 3, 4, 6, 7, 9, 10
7#9 0, 1, 3, 4, 6, 8, 10

例如,Cmaj7 和弦的音阶是 {C, D, E, G, A, B}(和弦被标识为根音和调式写成一个单词)。

即兴演奏是音符和/或停顿的有限序列。

对于给定的音符 $x$,最接近且适合和弦 $A$ 的音符是序列 $x$, next($x$), prev($x$), next(next($x$)), prev(prev($x$)), ... 中第一个适合 $A$ 的元素。next($x$) 表示经典顺序中 $x$ 之后的下一个音符,prev($x$) 表示经典顺序中 $x$ 之前的音符。

即兴演奏算法可以用伪代码表示:

Algorithm's input:     sequence of accords P, improvisation I,
                    length of the sequence of accords m, length of the improvisation n
Result:             improvisation J
Variables:             integer i, integer p
J := sequence of length n containing only pauses
p := 1
for i := 1 to n do begin
    if I[i] <> pause then begin
        J[i] := nearest note to I[i] which fits to P[p]
        if i mod 4 = 0 then begin
            p := p + 1
            if p > m then p := 1
        end
    end
end

实现即兴演奏算法。编写一个程序,该程序:

  • 从标准输入读取和弦序列和即兴演奏,
  • 根据即兴演奏算法,找到适合给定和弦的即兴演奏,
  • 将结果写入标准输出。

输入格式

第一行包含一个整数 $m$,$1 \le m \le 100\,000$。第二行包含一个和弦序列,写为 $m$ 个和弦,以空格分隔。第三行包含一个整数 $n$,$1 \le n \le 100\,000$。第四行包含 $n$ 个音符和/或停顿,以空格分隔,代表一段即兴演奏。

输出格式

输出应为一行,包含 $n$ 个音符和/或停顿,代表生成的即兴演奏,以空格分隔。

说明:当显示一个有两种不同表示形式的音符时,需要根据算法伪代码第 5 行的和弦 $P[p]$ 使用相应的表示形式:如果和弦的根音带有降号,则应使用带降号的表示形式。否则,应使用带升号的表示形式。

样例

输入 1

2
Gb7 Bb7
12
C C# D D# E F _ F# G _ G# A

输出 1

Db Db Eb Eb F F _ G Ab _ Ab Bb

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.