今天,是我们入营的第一天,进行了开营测试。已经一个月没有碰电脑的我,硬着头皮上了。。。。。。
T1:
音阶(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小调中就是A、D、E,在C大调中就是C、F、G。我们把这些音叫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。有10个C大调的main tones,6个A小调的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
这题,是一道大水题,非常容易AC,不多说。#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
freopen("ljestvica.in","r",stdin);
freopen("ljestvica.out","w",stdout);
int a=0,c=0;
string st;
cin>>st;
if(st[0]=='A'||st[0]=='D'||st[0]=='E')
{
a++;
}
if(st[0]=='C'||st[0]=='F'||st[0]=='G')
{
c++;
}
for(int i=1;i<st.length();i++)
{
if(st[i]=='|')
{
int j=i+1;
if(st[j]=='A'||st[j]=='D'||st[j]=='E')
{
a++;
}
if(st[j]=='C'||st[j]=='F'||st[j]=='G')
{
c++;
}
}
}
if(a>c)
{
cout<<"A-mol"<<endl;
}
if(c>a)
{
cout<<"C-dur"<<endl;
}
if(a==c)
{
if(st[st.length()-1]=='A'||st[st.length()-1]=='D'||st[st.length()-1]=='E')
{
cout<<"A-mol"<<endl;
}
else
{
cout<<"C-dur"<<endl;
}
}
return 0;
}
T2;
波老师(teacher/1S/64M)
【题目描述】
波波老师是一个地理老师。有一天他上课的时候,他在地图上标记了N个点,第i个点在点(Xi,Yi)。他想知道,是否存在四个点(A,B,C,D)(A<B,C<D,A≠C或者B≠D),使AB之间的曼哈顿距离和CD之间的曼哈顿距离相等。
如果存在这样的四个点,输出YES,否则输出NO。
【输入格式】
输入文件第一行是一个T(T≤50),表示有T组数据。
接下来有T组数据,每组数据第一行是两个整数N,M,表示点的个数以及点的坐标的边界,然后有N行,第i行有两个整数Xi,Yi表示第i个点的坐标(Xi,Yi)(0≤Xi,Yi≤M)
【输出格式】
输出文件有T行,每一行为YES或者NO。
【输入】
2
3 10
1 1
2 2
3 3
4 10
8 8
2 3
3 3
4 4
80% n<=1000,m<=100000
100% n<=100000,m<=100000
【输出】
YES
NO
这一题,80分很简单(只要不一边读入,一边break就行了,这样会使内容未读完而被误认为是下面的内容,所以,我们应该先读完再操作)100分,只需要发现,在所有的路径中,最短是1,最长是200000,所以,最多只有200000种情况。当某种方案超过2000000种时,根据鸽巢原理(抽屉原理),其中一定有相同的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct hehe
{
int x;
int y;
};
hehe num[100001];
bool pd[200002];
int main()
{
freopen("teacher.in","r",stdin);
freopen("teacher.out","w",stdout);
int t,n,m;
cin>>t;
for(int i=0;i<t;i++)
{
memset(num,0,sizeof(num));
memset(pd,false,sizeof(pd));
cin>>n>>m;
bool ex=false;
for(int i=0;i<n;i++)
{
cin>>num[i].x>>num[i].y;
}
if((n)*(n+1)/2>m)
{
cout<<"YES"<<endl;
continue;
}//鸽巢原理
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(num[i].x<=m&&num[i].y<=m&&num[j].x<=m&&num[j].y<=m)
{
if(pd[abs(num[i].x-num[j].x)+abs(num[i].y-num[j].y)])
{
ex=true;
break;
}
else
{
pd[abs(num[i].x-num[j].x)+abs(num[i].y-num[j].y)]=true;
}
}
}
}
if(!ex)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
爆裂吧世界(world/1S/64M)
【题目描述】
给你一个长度为n的数列A,请你计算里面有多少个四元组(a,b,c,d)满足:
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad
【输入格式】
输入文件第一行有一个整数N,第二行有N个整数A1,A2⋯An
【输出格式】
【输入1】
4
2 4 1 3
【输出1】
1
【输入2】
4
1 2 3 4
【输出2】
0
【数据约定】
15% n<=100
100%n<=50000
A在int范围里
这题,难度是有的,但是不大,在做的时候不够时间。简单来说,就是树状数组+容斥原理。
用树状数组用求出逆序对的方法求出每个数当b,c有多少种(两个树状数组)。
然后我们发现,b+d=这个数前面的数-1.因为前面的数不是比他大就是比他小。
a+c=这个数后面的数-1,理由同上。
然后,算出一共有多少种组合。
再用总数-(某个数同时做a,c.a,d.b,c.b,d).因为只有这四种。
就得出了最后的答案。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int sum[50005];
int ansb[50005],ansc[50005],ansa[50005],ansd[50005];
int n;
int query(int x)
{
int ans1=0; //计算1-x的和
for (ans1 = 0;x>0;x -= (x & (-x)))//求x变成二进制后第一个1的位置
ans1+=sum[x];
return ans1;
}
int change(int x,int delta){//改变第x个数,让他加上delta
for ( ;x<=n;x += (x & (-x)))
sum[x] += delta;
}
struct hehe
{
int m;
int op;
int np;
};
hehe num[50001];
int cmp(hehe x,hehe y)
{
return x.m<y.m;
}
int cmp1(hehe x,hehe y)
{
return x.op<y.op;
}
int main()
{
freopen("world.in","r",stdin);
freopen("world.out","w",stdout);
long long tot=0,tota=0,totc=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>num[i].m;
num[i].op=i;
}
sort(num+1,num+n+1,cmp);
int i1=0;
for(int i=1;i<=n;i++)
{
if((i==1)||(num[i].m!=num[i-1].m)) i1++;//防止两数相等
num[i].np=i1;
}
sort(num+1,num+n+1,cmp1);
for(int i=1;i<=n;i++)
{
ansb[i]=query(num[i].np-1);//求b
ansd[i]=i-1-query(num[i].np);//注意这里是没有减一的
change(num[i].np,1);
}
memset(sum,0,sizeof(sum));
for(int i=n;i>=1;i--)
{
ansc[i]=query(num[i].np-1);
ansa[i]=n-i-query(num[i].np);
change(num[i].np,1);
}
for(int i=1;i<=n;i++)
{
tota+=ansa[i];
totc+=ansc[i];
}
tot=tota*totc;
for(int i=1;i<=n;i++)
{
tot-=(long long)ansa[i]*ansc[i];
tot-=(long long)ansa[i]*ansd[i];
tot-=(long long)ansb[i]*ansc[i];
tot-=(long long)ansb[i]*ansd[i];
}
cout<<tot<<endl;
return 0;
}