2016-8-4夏令营入营测试总结

30 篇文章 1 订阅
23 篇文章 0 订阅

本次的测试从思维和编程角度上来说都是很简单的,然而在时间上却并不简单。虽然说我们现在的水平已经相当不错,但是考的仍然不是很好,估计是久离算法的缘故了。

题目的链接是http://pan.baidu.com/s/1hrIQMry
【T1:音阶】
这题很水,直接做吧,只不过要注意题目中是“最后一个音符”而不是“最后一节的重音”。

/*
A MT : A D E
C MT : C F G
*/
# include <cstdio>
# include <cstring>
using namespace std;
const int MAXL = 120;
char music[MAXL];
int A_MT,C_MT;
int main(){
    freopen("ljestvica.in","r",stdin);
    freopen("ljestvica.out","w",stdout);
    scanf("%s",music);
    int len = strlen(music);
    bool nowisFirst = true;
    A_MT = C_MT = 0;
    for (int i=0;i<len;++i){
        if (nowisFirst){
            if (music[i] == 'A' || music[i] == 'D' || music[i] == 'E') ++A_MT;
            if (music[i] == 'C' || music[i] == 'F' || music[i] == 'G') ++C_MT;
        }
        if (music[i] == '|') nowisFirst = true;
        else nowisFirst = false;
    }

    if (A_MT == C_MT)
        if (music[len-1] == 'C' || music[len-1] == 'F' || music[len-1] == 'G')
            printf("C-dur");
        else printf("A-mol");
    else if (A_MT > C_MT) printf("A-mol");
    else printf("C-dur");
    return 0;
}

【T2:波老师】
真是奇怪的题目……好吧这题有个很简单的暴力,就是 O(n2) 的,但是用一点常数的优化就多过了 20% 的数据……那数据的范围可是从 1000 106 啊……好吧不吐槽出题人了,先放程序:

# include <algorithm>
# include <cstring>
# include <cstdio>
# include <cmath>
using namespace std;
const int MAXN = 2000010;
pair<int,int> Point[MAXN];
int T;
int n,m;
/*Water!*/
//int MLen[MAXN*MAXN];
bool f[MAXN];
bool found;
//int size = 0;

int main(){
    freopen("teacher.in","r",stdin);
    freopen("teacher.out","w",stdout);
    scanf("%d",&T);
    for (int kase = 0 ; kase < T ; ++kase){
        /*Initial*/
        memset(f,false,sizeof(f));
    //  size = 0;

        scanf("%d%d",&n,&m);
        for (int i=0;i<n;++i){
            scanf("%d%d",&Point[i].first,&Point[i].second);
        }
        sort(Point+0,Point+n);
        /*Water!*/
        found = false;
        for (int i=0;i<n;++i){
            for (int j=0;j<i;++j){
                int dis = abs(Point[i].first-Point[j].first)+abs(Point[i].second-Point[j].second);
                if (f[dis]){
                    found = true;
                    break;
                }
                else f[dis] = true;
            }
        }

        /*
        bool found = false;
        sort(MLen+0,MLen+size);
        for (int i=1;i<size;++i){
            if (MLen[i] == MLen[i-1]){
                found = true;
            }
        }
        */

        if (found) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

好吧另外补一下,其实这其中有用到鸽巢原理的……考虑到,其实只有最多 2×106 种的不相同的曼哈顿距离,所以这个break就使得时间复杂度变成了 O(min(n2,2×m)) !确实,有是一个break就有神效。

【T3:爆裂吧世界】
先吐槽一下名字~出题人没有改过来吧。好吧,这题的思维难度比较大,而我是在临考试结束前十几分钟时想出来的,根本没有时间编了~然而我的想法和出题人的一样……
好吧不说废话了,这道题目题面已经足够明晰,那么对于其的做法,我们先要参考一下逆序对的树状数组解法,在这里我们可以知道如何求出在第 i 个数前面并且比第i个数小的数的个数了,而且以此类推还可以求出在第 i 个数后面的那些啊,比第i个数小的那些啊……
总之很简单。那么我们考虑一下这个能干什么。考虑将这个四元组 (a,b,c,d) 分成两个双元组 (a,b) (c,d) ,然后我们统计第 i 个数分别作为其中的abcd,并分别求方案数。那么,我们先想想看,如果我们求出两个双元组各自的方案数,再乘起来,得到的是答案吗?显然不是,因为题目要求 abcd ,但是直接应用乘法原理很有可能会使得不等号不成立。那么怎么办呢?减掉等于的部分!怎么减呢?容斥原理!先考虑没有限制的,就是乘法原理直接乘,然后有两个互相相等的有 6 种情况,但是可以排除掉两种,a=b c=d ,因为本身我们求方案数的时候就没有这两种情况。同理,三个和四个互相相等的都一定会有这种情况,所以都会排除。如果用 P{...} 来表示相应的方案数,那么有

P{abcd}=P{a?b?c?d}P{a=c}P{a=d}P{b=c}P{b=d}

然后相应求出来就好了。怎么求呢?这里以 P{a=c} 为例,如果 a=c ,那么我们现在要的就是先枚举一个 i ,然后统计另外独立存在的b d ,也就是分别将i作为 a c,统计相应的 (i,b) (i,d) 的方案数,由于其独立存在,所以用乘法原理乘起来就好了。像 (i,b) 的方案数实际上就是在第 i 个数后面并且比第i个数大的数的个数,其余以此类推,我们就可以求出 P{a=c}=i=1nP{i,b}×P{i,d} ,其余的几个也可以用类似的方法求出。
于是便求完了,代码如下:

/*
目前并没有写完,稍后补上
*/

其实这道题并不难,只是代码量有点大,不是那种能在 5 <script type="math/tex" id="MathJax-Element-5250">5</script>分钟内编完的类型……

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值