概念:
①初始化的数组,其下标是从0开始计数!
②数组的下标是 int 类型,下标具有唯一性!
第1题 小鸟(程序填空)【L1】
有n只小鸟,依次读入n只小鸟的类型,小鸟类型的是一个正整数。有m次询问,每次询问给出一个a,表示询问有多少只小鸟的类型是a。
输入格式
第一行,一个整数n。1<=n<=100000。
第二行,n个正整数,第i个整数表示第i只小鸟的类型,范围是[1,1000000]。
第三行,一个询问次数m。1<=m<=100000。
第四行,m个正整数,第i个整数a表示询问类型是a的小鸟的数量。
输出格式
一行,共m个整数,每个整数对应一个询问的答案,空格分开。
输入/输出例子1
输入:
5
2 10 8 9 2
3
8 11 2
输出:
1 0 2
样例解释
方法一:
把n个整数读入保存到数组。
对于每一个询问,用一个for循环扫描数组,统计x出现的次数。有m次询问,每次询问扫描一遍数组需要扫描n个元素,所以时间复杂度是O(n*m)=10^5 * 10^5 = 10^10,约需要10秒,超时。
方法二:
可以假设有1000000只鸟笼,编号是1至1000000,一开始所有笼子都没有小鸟,然后有n只小鸟排队依次飞进鸟笼,类型x的小鸟会飞进编号是x的鸟笼。然后对于每一个询问a,只需要回答编号是a的鸟笼有多少只小鸟即可。可以用数组box[10000005]来表示1000000只鸟笼,用box[i]记录编号是i的鸟笼目前有多少只小鸟。然后用for循环读入每只小鸟的类型,模拟小鸟飞进鸟笼的过程,假设第i只小鸟的类型是x,那么它会飞进编号是x的鸟笼,该鸟笼的小鸟数量加1,也就是box[x]++即可。当所有小鸟都飞进鸟笼之后,对于每一个询问,输出相应的鸟笼里面小鸟数量即可,例如询问类型是a的小鸟的数量,只需要输出box[a]即可。
练习一
第1题分糖果(程序填空)【L2】
有n个小朋友,学号从1至n。圣诞节会有m次分糖互动,第i次活动给学号是a至b的小朋友分1颗糖果。问哪个小朋友得到的糖果数量最多?
输入格式
第一行,两个整数n和m。1<=n,m<=5000。
接下来有m行,每行两个整数a和b。1<=a<=b<=n。
输出格式
一个整数,表示得到最多糖果的那个学生的学号,如果有多位学生得到的糖果都是最多的,那么输出他们当中学号最大的。
输入/输出例子1
输入:
10 2
3 5
4 10
输出:
5
例题二
第1题数组计数排序(程序填空)【L9】
有n(n<=10000)件物品,依次读入这n件物品的重量,每件物品重量都不超过10000的整数,现在你要按照从轻到重的次序,输出这n件物品的重量。
分析问题
第一步,开一个数组c[10005],其中c[i]保存的是有多少件重量是i的物品,初始化c数组为0,表示暂时没有任何物品。
第二步,用循环读入n件物品的重量,设第i件物品重量是x,那么就让c[x]++,表示重量是x的物品增加了一件。
第三步,用循环从1枚举到10000,当枚举到i时,因为c[i]保存的是有多少件物品的重量是i,所以我们用循环输出c[i]个i。
这样就完成了从小到大排序的目标。
下面给出一个样例,假如输入的是:
7
3 6 7 3 7 8 3
输入格式
第一行,一个整数n。
第二行,n个正整数。
输出格式
从小到大排序后输出
输入/输出例子1
输入:
7
3 6 7 3 7 8 3
输出:
3 3 3 6 7 7 8
深入理解以下例子代码!先写下自己的方法,再去验证和对比参考代码。
例1:输入n个整数,存放在数组a[1]至a[n]中,输出最大数所在位置(n<=10000)。
输入样例:
5
67 43 90 78 32
输出样例:3
分析:设maxa存放最大值,k存放对应最大值所在的数组位置,maxa的初值为a[1],k的初值对应为1,枚举数组元素,找到比当前maxa大的数成为maxa的新值,k值为对应位置,输出最后的k值。
例2:有n个人,编号为1~n。开始时,所有人都站着,接着第2个人及2的倍数的人坐下,然后,第3个人及3的倍数的人按相反的操作(站的人坐下,坐的人站起来),依此类推,一共操作到第k人及k的倍数,问最后哪些人站着?输入n和k,输出站着人的编号(k≤n≤10000)。
输入样例:7 3
输出样例:1 5 6 7
分析:用a[1]、a[2]、…、a[n]表示编号为1、2、3、…、n的人是否站着,初值都为0,表示都站着,让i从2到k循环,将a数组中i倍数的元素值取反。输出a数组中值为0的元素。
例3:学校推出了10名歌手,校学生会想知道这10名歌手受欢迎的程度,设了一个投票箱,让每一个同学给自己喜欢的歌手投票,为了方便,学生会把10个歌手用1-10进行编号,这样,同学们只要用编号进行投票了。
现在,学生会找到你,帮助统计一下每个歌手获得的票数。
分析:
很直观的想法是,投谁,谁的票数加1。如:投2号,则2号的票数加1,投6号,6号的票数加1。如何表示这么一个操作过程呢?
设变量num[i]表示第i个歌手的票数,相当于用名称num表示票数,然后再对名称进行编号,编号为i的num表示第i个歌手的票数。这样,投2号,则2号的票数加1,就可以表达为:i=2;num[i] = num[i]+1投6号,则6号的票数加1,就可以表达为:i=6;num[i] = num[i]+1
归纳上述分析,具体实现步骤如下:
(1)开辟num[1]~num[10]变量分别存放10个歌手的票数。
(2)读入选票赋给i。
(3)对应选票i的歌手票数加1,即num[i]=num[i]+1。
(4)重复(2)和(3)的操作,直到读完选票为止。
(5)输出每位歌手的票数。
例4:输入n个数,存入数组a中,每一个数都是介于0到k之间的整数,此处k为某个整数(n≤100000,k≤1000),按从小到大的顺序输出a数组中的数据。
分析:看了问题,我们直观的想法是将a数组中的数据实现从小到大的顺序排序。排序的方法有多种,效率也不一样。但本问题有一个重要的特点就是每一个数都是介于0到k之间的整数,而且k的值很小,我们可以开设一个下标为0~k的数组c,c[0]记录a数组中值为0的个数,c[1]记录a数组中值为1的个数,……,c[k]记录a数组中值为k的个数,那么按从小到大的顺序输出个数为c数组元素值的c数组下标值,即按从小到大的顺序输出a数组中的数据。
实现步骤如下:
(1)读入数据存放在a数组中,设数组c,c[x]存放值为x的个数。
(2)对于a数组中的n个数,统计值为ai]的个数,c[ a[i] ] - c[ a[i] ]+1。
(3)循环i:0~k,输出c[i]个i。
例5:给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0~9的拼法如图5.1所示。输入整数n(n<=24),输出能拼成的不同等式的数目。
注意:
(1)加号与等号各自需要两根火柴棍。
(2)如果A!=B,则A+B=C与B+A=C视为不同的等式(A、B、C>=0)。
(3)n根火柴棍必须全部用上。
输入样例:18
输出样例:9
输出样例解释:
0+4=4
0+11=11
1+10=11
2+2=4
2+7=9
4+0=4
7+2=9
10+1=11
11+0=11
分析:设等式中的三个变量为A、B、C,如果已知A和B,则C=A+B。
由于题目给出的火柴数目范围很小,可以穷举A、B值,求得C值,求出构成等式A+B=C的火柴数目,如果火柴数目为输入值,则为问题的一个解,累计解的个数即为本问题的最终答案。
对于本题,我们能否从细节上提高穷举的效率呢?
(1)根据n<=24条件,确定穷举A和B的范围。即如果都使用最少火柴的数字(如数字1)构造表达式中的数,得到最大的数是多少,可以算出该数<1000,因此A和B的范围为0~1000。
(2)在穷举表达式过程中,需要反复计算每个数所用的火柴数目,即相同的数有可能重复计算许多次的火柴数目,显然,需要想办法减少重复计算。先进行预处理,将估算范围内的数所用的火柴数目算出。
(3)穷举过程中如果当前数的火柴数目超过输入限制做剪枝处理。
归纳上述分析,具体实现步骤如下:
(1)预处理:求0~2000数对应的火柴数目。
(2)使用循环枚举A值0~1000,执行下列操作:
①判断A值的火柴数目是否超过限制值,是的,剪枝,跳过该数的处理。
②否,使用循环穷举B值0~1000,执行下列操作:
·判断A和B值的火柴数目和是否超过限制值,是的,剪枝,跳过该数的处理。
·否,求C值,若A、B、C值火柴数目和等于限制值,计数方案数。
(3)输出方案数。