教你AK2017年12月30日迎新挑战赛前三题

1.毛烨超的IQ

  (iq.pas/c/cpp)

【问题描述】

 

     N年后,毛烨超已经是世界某权威学会的会长,他发现自从学信息学竞赛以来,他的智商也在飞速增加,于是他利用大数据和人工智能做了一项调查,发现学信息学学生的IQ真的非常高。举个最好的例子,如果我们把学信息学的一些学生调去学数学,那么两个竞赛的学生平均IQ都会提升。现在给出一群数学竞赛全体学生的IQ和信息学竞赛全体学生的IQ,问最多能把几个学信息学的学生调去学数学,而两个竞赛的学生平均IQ都有提升呢?

每次只调一个学生,而且每次调配,两个竞赛的学生平均IQ都要提升。

【输入】

第1行,一个正整数N(N<=100),代表数学竞赛班学生的数目。

第2行,有N个正整数,代表每个数学学生的IQ(1-200之间)。

第3行,一个整数M(M<=100),代表信息学竞赛班学生数目。

第4行,有M个正整数,代表每个信息学竞赛班学生的IQ(1-200之间)。

输入数据保证信息学学生平均IQ高于数学学生。

【输出】

一个正整数,代表能从信息学调去学数学的学生的个数。

 

 

【输入输出样例1】

iq.in

iq.out

3

3 2 3

3

3 2 5

1

 

  


 

一开始我做这道题的时候, 我题目都就读了好几遍, 我觉得这道题目有点难懂。

高度概括一下:就是把信息班的学生调到数学班,然后这两个班级的平均智商都变高,那么这个就是一个成功的例子,就总个数累加。最后把总个数输出,那么就是正确答案了。

    一下子能想到的就是排序,没错,排序就是一个很方便的算法,它可以使这道题目简化许多,从小到大将信息班人员数据排序,为什么一排序就把这道题减化许多了?因为第二组从小到大排序之后,当前一个数据移到数学班时不能成立(即数学班或者信息班的平均分降低。)则下面后面几个数据都不能移到数学班,这只会使信息班的平均分更加拉低,而模拟则会比较麻烦,需要好几重循环。

    于是代码就可以敲出来了,先进行输入,然后将信息班人员进行,从小到大排序,再从一到信息班人员人数循环,进行判断:如果转换后,数学班和信息班的平均分变高,那么这是一组成立的例子总和加一将平均分重新覆盖成新的。反之,就把平均分改成原来的,也就是说这个方案是不成立的。

    代码贴一下:

include <bits/stdc++.h>

using namespace std;

int main()

{

    intn,m,i,j,nax2=0,max2=0,x,y,count=0,sum,ans;

    doublenax1=0,max1=0;

    inta[1000]={},b[1000]={};

    cin>>n;

    for(i=1;i<=n;i++)

    {

       cin>>a[i];

       nax2+=a[i];

    }

    cin>>m;

    for(j=1;j<=m;j++)

    {

       cin>>b[j];

       max2+=b[j];

    }  

    sum=nax2;ans=max2;

    nax1=double(nax2)*1.0/n*1.0;max1=double(max2)*1.0/m*1.0;

    x=n;y=m;

    sort(a+1,a+n+1);

    sort(b+1,b+m+1);

    for(i=1;i<=m;i++)

       if((sum+b[i])*1.0/(x+1)*1.0>nax1 && (ans-b[i])*1.0/(y-1)*1.0>max1)

       {

           x++;

           y--;

           sum=sum+b[i];

           ans=ans-b[i];

           nax1=(sum*1.0)/(x*1.0);

           max1=(ans*1.0)/(y*1.0);

           count++;

       }

           else

           {

              x=n;

              y=m;

              sum=nax2;

              ans=max2;

           }

    cout<<count;

    return0;

}

代码有点乱,请见谅。

 

2.黄旭彬家的工厂

  (prod.pas/c/cpp)

 

                           黑皮宝典上有,自己看。

3.杨佳涵家的树

  (eko.pas/c/cpp)

【问题描述】

 

    杨佳涵家有万亩树林,他的好朋友陈卓需要一些木头,于是杨佳涵指定了N棵树,每棵都有一个整数高度。陈卓需要的木头的总需要量为M。 现在需要确定一个最大的统一的砍树高度H,如果某棵树的高度大于H,则高出的部分被砍下。使得所有被砍下的木材长度之和达到M(允许稍超过M)。

例如,有4棵树,高度分别是20 15 10 17,需要的木材长度为 7,砍树高度为15时,第1棵树被砍下5,第4棵树被砍下2,得到的总长度为7。如果砍树高度为16时,第1棵树被砍下4,第4棵树被砍下1,则得到的木材数量为5。给定N和M,请你编程帮杨佳涵和陈卓求出砍树的高度 H。

 

【输入】

第1行:2个整数N和M,N表示树木的数量(1 ≤ N ≤ 1 000 000),M表示需要的木材总长度(1 ≤ M ≤ 2 000 000 000)。

第2行: N个整数表示每棵树的高度,值均不超过1  000  000  000。所有木材高度之和大于M,因此必然有解。

【输出】

第1行:1个整数,表示砍树的最高高度。

 

【输入输出样例1】

eko.in

eko.out

5 20
4 42 40 26 46

 

36

  


这道题目一看数据就知道,正解应该是二分查找。

但仔细看就会发现这个数据有点小啊,那么也就是说你用模拟也是可以AK的。

我用的就是模拟的方法。

利用铜牌的思想,在输入数据的同时,将最大值找到,并将这些数放入桶。然后从那个最大的数据一个一个往下推,值到你砍下来的高度之和大于m或者等于m。然后你将这个高度输出就行

要注意的是他砍下来的木材长度是指高出的长度,当树的高度等于这个要砍的高度的时候是不能算的。

于是,代码如下:

#include <bits/stdc++.h>

using namespace std;     

int n,m,i,j,sum=0,Max=-100,c=0;

int a[100000001];

int main()

{

      cin>>n>>m;

      for(i=1;i<=n;i++)

      {

           cin>>j;

           if(j>Max) Max=j;

           a[j]++;

      }

      for(i=Max;sum<m;i--)

      {

           c=c+a[i];

           sum=sum+c;

      }

      cout<<i;

      return 0;

}

Lt is so easy!

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值