[0705]Tyvj 1498 [GDOPI2011] 乐谱变调

时间:2021-10-09 12:45:01
【問題描述】
大家應該聽過很多美妙動聽的歌曲,也曾經在卡拉OK中唱過不少歌曲。其實,很多歌曲的調子都經過了變調,因為很多歌曲原來的調子一般都偏高,需要把調適當 降低,才適合一般人歌唱。現在請你編程解決這個變調的問題,把一個曲譜從原來的調子基礎上,升高或降低若干個調,變成一個新的曲譜。
【音階】
相信大家都見過電子琴,也聽過電子琴,琴中的每個白色鍵,代表的是簡譜中的1,2,3,4,5,6,7的音階,用字母代表即為 C,D,E,F,G,A,B,見下圖:
[0705]Tyvj 1498 [GDOPI2011] 乐谱变调

此外,上面的黑鍵表示半音,按照上圖,從左邊到右邊的5個黑鍵代表的半音為:#C,#D,#F,#G,#A

由最左邊的音階C數起到第七個音階B,中間的黑鍵和鍵,均處於一個基準八度區域,在B右邊的琴鍵,比原來的音階高一個八度區域,稱為高八度區域; C音階左邊的琴鍵(圖片沒有顯示),比原來的音階低一個八度區域,稱為低八度區域。
【樂譜】
一個歌曲的樂譜,包括音階、節奏、小節線、休止符等元素,這裡為了簡單表示,只保留音階這一元素,節奏、小節線、休止符不在此題目中展現。
樂譜中的每個音階,可以用C,D,E,F,G,A,B,#C,#D,#F,#G,#A 表示。
在樂譜中會牽涉到八度區域的遷移問題,我們使用 “>”、“<” 來變化當前的八度區域。其中“>”表示提高當前八度區域(例如從低八度區域=>基準八度區域),“<”表示降低當前八度區域(例如高八 度區域=>基準八度區域)。樂譜一開始的時候,當前八度區域為基準八度區域。
【樂譜變調】
對一個樂譜,提高或者降低N個半音的操作,成為樂譜變調。
首先,對於一個八度區域中,以下音階均相隔一個半音。
C,#C,D,#D,E,F,#F,G,#G,A,#A,B
然後,B音階比高它一個八度區域的C音階,相隔一個半音
變調就是一個簡單的升降音階的操作,只要數著半音階個數修改音階即可。例如,C音階提高6個半音,數過去就是#F,B音階提高4個音階,則為下一個八度區域的 #D 音階,同理,#F降6個半音階(升-6個半音)則為C。
【輸入格式】
輸入第一行字元串,包含上面的各個音階,以及>/<符號,表示一個樂譜,樂譜字元串長度<=200,沒有空格和其他字元串。
輸入第二行為整數N (-16<=N<=16) ,表示升多少個半音
【輸出格式】
輸出為一行字元串,代表樂譜。
【輸入樣例】
CDEFGAB>C
2
【輸出樣例】
DE#FGAB>#CD
 1  const
 2     a: array[ 1.. 12of string
 3   =( ' C ', ' #C ', ' D ', ' #D ', ' E ', ' F ', ' #F ', ' G ', ' #G ', ' A ', ' #A ', ' B ');
 4  var
 5   i,j,k,s,n,prev,PresentStage:integer;
 6   st:string;
 7   p: array[ 1.. 300of string;
 8   now,stage: array[ 1.. 300of integer;
 9  begin
10   readln(st);
11   readln(n);
12   i:= 1;
13   j:= 0;
14   s:= 1;
15    while i<=length(st)  do
16     begin
17       if st[i]= ' < '  then
18        begin
19         s:=s- 1;
20         inc(i);
21        end
22       else
23         if st[i]= ' > '  then
24          begin
25           s:=s+ 1;
26           inc(i);
27          end
28         else
29           if st[i]= ' # '  then
30             begin
31              inc(j);
32              stage[j]:=s;
33              p[j]:=copy(st,i, 2);
34              i:=i+ 2;
35             end
36            else
37              begin
38               inc(j);
39               stage[j]:=s;
40               p[j]:=copy(st,i, 1);
41               i:=i+ 1;
42              end;
43     end;
44    for i:= 1  to j  do
45     begin
46       for k:= 1  to  12  do  if p[i]=a[k]  then prev:=k;
47      now[i]:=prev+n;
48       while now[i]> 12  do
49        begin
50         now[i]:=now[i]- 12;
51         stage[i]:=stage[i]+ 1;
52        end;
53       while now[i]< 1  do
54        begin
55         now[i]:=now[i]+ 12;
56         stage[i]:=stage[i]- 1;
57        end;
58     end;
59   PresentStage:= 1;
60    for i:= 1  to j  do
61     begin
62       if stage[i]<PresentStage  then
63        begin
64         write( ' < ');
65         dec(PresentStage);
66        end
67       else
68         if stage[i]>PresentStage  then
69          begin
70           write( ' > ');
71           inc(PresentStage);
72          end;
73      write(a[now[i]]);
74     end;
75  end.
AC100 Cheers!!!