2016.8.4入营测试

来源:互联网 发布:excel数据透视表快捷键 编辑:程序博客网 时间:2024/05/29 15:21

1.音阶(ljestvica/1S/64M)

·题目大意:
 给出一串音符,判断TA是A小调还是C大调。给出了以下定义:①重音是一个小节开头的音②A小调的主音是A、D、E,C大调的主音是C、F、G。③由重音中是A小调的主音多还是C大调的主音多判断这首曲是A小调还是C大调,如果主音数相同,若最后一个音是A小调的主音,这首曲子就是A小调,否则就是C大调。
·数据规模:
 序列长度不超过100。
·解题思路:
 这题的原题目比较长,但是这题并不难,从题中可以看出是一道模拟题,数据规模很小。直接做就可以了。
·注意事项:
 看题时要仔细,尤其是题目长的时候,不要漏掉了关键点,有必要时可以做标记。
·代码:

#include <iostream>#include <fstream>#include <string>using namespace std;ifstream fin("ljestvica.in");ofstream fout("ljestvica.out");#define cin fin#define cout foutstring s;int counta=0,countc=0;int pd(char c) //判断音符是C大调orA小调 {    if (c=='A' || c=='D' || c=='E') return 1;     if (c=='C' || c=='F' || c=='G') return 2;    return 0;}int main(){    bool f;    cin >> s;    f=true;    for (int i=0;i<s.size();i++)    {        if (f)         {            if (pd(s[i])==1) counta++; //统计             if (pd(s[i])==2) countc++;            f=false;        }        if (s[i]=='|') f=true; //利用f取出重音     }//  cerr << counta << ' ' << countc << '\n';    if (counta==countc) //判断重音个数相等情况     {        if (pd(s[s.size()-1])==1) cout << "A-mol\n";        else cout << "C-dur\n";        return 0;    }    if (counta>countc) cout << "A-mol\n";    else cout << "C-dur\n";    return 0;}

2.波老师(teacher/1S/64M)

·题目大意:
 给出n个点,坐标为(x,y)(0≤x,y≤m),问是否存在四个点(A,B,C,D)(A﹤B,C﹥D,A≠C或者B≠D),使AB之间的曼哈顿距离和CD之间的曼哈顿距离相等。(多组数据)

曼哈顿距离:两个点在标准坐标系上的绝对轴距总和。

·数据规模:
 80% 1≤n≤1000
 100% 1≤T≤50 , 1≤n≤50000 , 0≤m≤100000
·解题思路:
 首先看80%的数据,n不超过1000,就可以用暴力的方法:将每两个点之间的曼哈顿距离都计算出来,用一个计数数组保存下来,发现被计了一次以上的就输出YES,否则输出NO。但仔细看这道题,就会发现两个坐标值最大都是10^5,也就是说,最多也只有2×10^5种,所以只要在计算曼哈顿距离时就判断,一找到就退出,时间复杂度最多为O(2×10^5),不会超时。
·注意事项:
 不要重复算A-B和B-A的距离。
·代码:

#include <iostream>#include <fstream>#include <algorithm>#include <string.h>#include <cmath>#include <math.h>using namespace std;ifstream fin("teacher.in");ofstream fout("teacher.out");#define cin fin#define cout foutint n,m;bool f[200006];int x[100006],y[100006];void work() //处理 {    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)//不要重复        {            if (f[abs(x[i]-x[j])+abs(y[i]-y[j])]) //判断是否已有相同曼哈顿距离             {                cout << "YES\n";                return ;  //省去不必要的计算,节省时间             }            f[abs(x[i]-x[j])+abs(y[i]-y[j])]=true; //标记         }    cout << "NO\n";}int main(){    int q;    cin >> q;    for (;q>0;q--)    {        memset(f,false,sizeof f);        cin >> n >> m;        for (int i=0;i<n;i++) cin >> x[i] >> y[i];        work();    }}

爆裂吧世界(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
·数据规模:
 15% n <= 100
 100% n <= 50000
·解题思路:
 首先看15%的数据,可以直接枚举,O(n^4),刚好10^8,危险过15%。
 100%就要用到数学上的一些技巧,首先树状数组求出b,d(或a,c)的可能数量,相乘,再用容斥原理去重即可(具体看程序)。
·代码:

#include <iostream>#include <fstream>#include <algorithm>#include <string.h>#include <cmath>#include <math.h>using namespace std;ifstream fin("world.in");ofstream fout("world.out");#define cin fin#define cout foutstruct num{    int value,pos;    num() { value=pos=0; }};num A[50006];int b[50006],f[50006];int sl[50006],sr[50006],bl[50006],br[50006];long long ans1,ans2,ans;int n;bool _cmp(num a,num b){    return a.value<b.value;}/*------------树状数组-------------*/void add(int pos) //表示增加一个大小为pos(已离散化)的数 {    for (;pos<=n;pos+=(pos & (-pos))) f[pos]++;}long long ask(int pos) //询问比pos(已离散化)小的数的个数 {    int sum=0;    for (;pos>0;pos-=(pos & (-pos))) sum+=f[pos];    return sum;}/*---------------------------------*/int main(){    int npos=1;    cin >> n;    for (int i=1;i<=n;i++)     {        cin >> A[i].value;        A[i].pos=i;  //记录原始位置     }    sort(A+1,A+n+1,_cmp);    for (int i=1;i<=n;i++) //离散化     {        b[A[i].pos]=npos;        if (A[i].value!=A[i+1].value) npos++;     }    memset(f,0,sizeof f);    for (int i=1;i<=n;i++)    {        sl[i]=ask(b[i]-1);  //处理i左边比TA小和大的数的个数         bl[i]=i-1-ask(b[i]);        add(b[i]);    }    memset(f,0,sizeof f);    for (int i=n;i>0;i--)    {        sr[i]=ask(b[i]-1); // 处理i右边比TA小和大的数的个数         br[i]=(n-i)-ask(b[i]);        add(b[i]);    }    for (int i=1;i<=n;i++)    {        ans1+=sl[i]; //统计a的方案数         ans2+=bl[i]; //统计b的方案数     }    ans=ans1*ans2;    for (int i=1;i<=n;i++) //利用容斥原理去掉重复     {        ans-=sr[i]*br[i]; //ac重复         ans-=bl[i]*br[i]; //ad重复        ans-=sl[i]*sr[i]; //bc重复        ans-=sl[i]*bl[i]; //bd重复    }    cout << ans << endl;    return 0;}
1 0
原创粉丝点击