音阶(ljestvica/1S/64M)

【题目描述】

Veronica进入了音乐学院。她收到了一张只有音符没有注释的乐谱,需要认出乐谱中用到的音阶。在本题中,我们只用到了两种最常用的(而且也是学校最先教的)音阶:A小调和C大调。这并不是说这两个音阶比其他大调、小调更简单或基础, 所有的小调和大调都是差不多的。

 

现代音乐中一个八度有12个音(A, A#, B, C, C#, D, D#, E ,F, F#, G, G#),A小调和C大调也是用这12个音组成。A小调是一组有序的七个音{A,B,C,D,E,F,G}C大调是{C,D,E,F,G,A,B}

 

注意,这两个音阶用到的音是一样的。那区别在哪?确定一个音阶,重点不仅在用到了什么音,还有他们的用法。主音(一个音阶的第一个音),下属音(第四个音),属音(第五个音)在一个音阶中是重音的首选。在A小调中就是ADE,在C大调中就是CFG。我们把这些音叫main tones

 

大调和小调有什么不同呢?比方说,A小调的中音(第三个音)比主音高三个半音,C大调的中音比主音高四个半音。总之,差别就在于两个相邻的音的距离。这使小调听起来伤感,大调听起来喜庆。

 

现在你要写一个程序判断这首曲子是用A小调写的还是用C大调写的。可以数在重音(每小节的第一个音)中是A小调的main tones多还是C大调的main tones多。如果main tones数相同,若最后一个音是A小调的main tones,这首曲子就是A小调,否则就是C大调。

 

比如说,现在来判断著名的旋律“你在睡觉吗?”;

CD|EC|CD|EC|EF|G|EF|G|GAGF|EC|GAGF|EC|CG|C|CG|C

字符“|”把每个小节隔开了,所以这个旋律的重音依次是:C,E,C,E,E,G,E,G,G,E,G,E,C,C,C,C。有10C大调的main tones6A小调的main tones,所以这个旋律是C大调的。

 

【输入格式】

输入文件仅一行, 包含一个序列(最短为5 最长100), 每个字母都包含在{A, B, C, D, E, F, G, |} 中。 其中”| 将每小节分开, 且不会出现在序列的开头或结尾。

 

【输出格式】

输出文件仅一行,为” C-dur C大调) A-mol A小调)。

 

【输入1

AEB|C

【输出1

C-dur

【输入2

CD|EC|CD|EC|EF|G|EF|G|GAGF|EC|GAGF|EC|CG|C|CG|C

【输出2

C-dur

================================================================

这题主要就是模拟,但要注重审题。Yhf神犇因为没有审好题导致只得了20分,而lkb呢也没有注意到细节,以致明明可以ac的题居然只得了70分。

具体的来说就是惯性思维害死人,没有看清楚题目结尾的一句话,“如果main tones数相同,若最后一个是”。前面的题目中提到的都是以“重音”来判断,导致lkb不假思索的也在main tones数相同的情况下,以重音来判断了。

这种“想当然”的思维很不好,在大型比赛中如果没有读好题甚至可能会导致爆零的严重后果。希望这次吸取了教训之后,以后能不再犯这种白痴错误。

只要审题清楚,那么便容易写出如下的模拟程序。

(写的不太优美,算是抛砖引玉吧。)

#include <cstdio>
#include <iostream>

using namespace std;

string st;
int A_mol = 0, C_dur = 0;
//分别记录重音中是A小调和C大调的main tones的数量

int main() {
ios::sync_with_stdio(false); //取消同步
freopen("ljestvica.in", "r", stdin);
freopen("ljestvica.out" , "w", stdout);
cin >> st;
char lastCh = st[st.size() - 1]; //取最后一个音
int last = (lastCh == 'C' || lastCh == 'F' || lastCh == 'G');
//看最后一个音是A小调还是C大调的main tones
st.append(1, '|'); //在结尾添加一条小节线方便处理

while(!st.empty()) {
//每小节取重音统计
if(st[0] == 'A' || st[0] == 'D' || st[0] == 'E')
++A_mol;

if(st[0] == 'C' || st[0] == 'F' || st[0] == 'G')
++C_dur;

//去掉本小节
st = st.substr(st.find('|') + 1, st.size());
}

if(A_mol != C_dur) //main tones数不相等的情况下直接判断
if(A_mol > C_dur)
cout << "A-mol" << endl;
else
cout << "C-dur" << endl;
else if(last == 0) //main tones数相等则判断最后一个音
cout << "A-mol" << endl;
else
cout << "C-dur" << endl;

return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值