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!