NOIP2018初赛总结(提高组)

更新完毕(纯手敲),如果有错误请在下面留言

单选题

T1.下列四个不同进制的数中,与其它三项数值上不相等的是

A.\((269)_{16}\)

B.\((617)_{10}\)

C.\((1151)_8\)

D.\((1001101011)_2\)

答案:D

实际上D比ABC要多2。这种题我一般先算2,8,16进制的,十进制难算,那三个很好互相转。

T2.下列属于解释执行的程序设计语言是

A.C

B.C++

C.Pascal

D.Python

答案:D

常识题。前三项都是编译型语言。

T3.中国计算机学会于?年创办全国青少年计算机程序设计竞赛。

A.1983

B.1984

C.1985

D.1986

答案:B

CCF颂歌题。凭感觉做题即可

upd:附上官方地址

背景:1984年邓小平指出:“计算机的普及要从娃娃做起。”中国计算机学会于1984年创办全国青少年计算机程序设计竞赛(简 称:NOI),当年参加竞赛的有8000多人。这一新的活动形式受到党和政府的关怀,得到社会各界的关注与支持。中央领导王震同志出席了首届竞赛发 奖大会,并对此项活动给予了充分肯定。从此每年一次NOI活动,吸引越来越多的青少年投身其中。十几年来,通过竞赛活动培养和发现了大批计算机爱好者,选 拔出了许多优秀的计算机后备人才。当年的许多选手已成为计算机硕士、博士,有的已经走上计算机科研岗位。

T4.设根节点深度为0,一棵深度为h的满k(k>1)叉树,即除最后一层无任何叶子节点外,每一层上的所有节点都有k个子节点的树,共有?个节点

A.\(\displaystyle\frac{k^{h+1}-1}{k-1}\)

B.\(k^{h-1}\)

C.\(k^h\)

D.\(\displaystyle\frac{k^{h-1}}{k-1}\)

答案:A

可以打表可以记结论,甚至你还可以现场推结论:等比数列求和。第0层的节点为1,第1层为k,第二层为\(k^2\),直到第\(h\)层为\(k^h\),等比数列求和公式为\(\frac{1-k^{h+1}}{1-k}\)即可选A。

T5.设某算法的时间复杂度函数的递推方程是T(n)=T(n-1)+n(n为正整数)及T(0)=1,则该算法的时间复杂度为

A.O(log n)

B.O(n log n)

C.O(n)

D.O(n^2)

答案:D

NOIP2015初赛第?题

T6.表达式\(a*d-b*c\)的前缀形式是

A.\(ad*bc*-\)

B.\(-*ad*bc\)

C.\(a*d-b*c\)

D.\(-**adbc\)

答案:B

卧槽慌得一批差点看成后缀表达式。可以直接模拟得到结果。

T7.在一条长度为1的线段上随机取两个点,则以这两个点为端点的线段的期望长度是

A.1/2

B.1/3

C.2/3

D.3/5

答案:B

可以通过几何概型+体积什么什么的求。建立一个三维坐标系Oxyz,x轴代表点A位置,y轴代表点B位置,z轴代表线段长度期望,那么长度的期望就是两个四面体拼起来的图形,顶点为(0,0,0),(1,0,0),(0,1,0),(0,0,1)和(1,1,0),(1,0,0),(0,1,0),(1,1,1)。这个几何体的体积为1/3(锥体体积为底面积乘以高再除以3),由于底面积为1,所以高度平均为1/3,即长度期望为1/3。zcysky的骗分思路也可以参考一下。

T8.关于Catalan数Cn=(2n)!/(n+1)!/n!,下列说法错误的是

A.Cn表示有n+1个节点的不同形态的二叉树的个数。

B.Cn表示含n对括号的合法括号序列的个数。

C.Cn表示长度为n的入栈序列对应的合法的出栈序列个数。

D.Cn表示通过连接顶点而将n+2边的凸多边形分成三角形的方法个数。

答案:A

A选项应该是n而不是n+1。可以把n=1、n=2时候暴力带入。

T9.假设一台抽奖机中有红、蓝两色的球,任意时刻按下抽奖按钮,都会等概率获得红球或蓝球之一。有足够多的人每人都用这台抽奖机抽奖,假如他们的策略均为:抽中蓝球则继续抽球,抽中红球则停止。最后每个人都把自己获得的所有球放到一个大箱子里,最终大箱子里的红球与蓝球的比例接近于

A.1:2

B.2:1

C.1:3

D.1:1

答案:D

考虑如果某个人抽中蓝球,就让他的儿子取抽球,那么每个人抽中红球蓝球的概率相等,那么答案为D。

T10.为了统计一个非负整数的二进制中1的个数,代码如下:

  1. int CountBit(int x)
  2. {
  3. int ret = 0;
  4. while (x)
  5. {
  6. ret++;
  7. _________;
  8. }
  9. return ret;
  10. }

则空格内要填入的语句是

A.x>>=1

B.x&=x-1

C.x|=x>>1

D.x<<=1

答案:B

假设二进制末尾是100000的形式,-1之后就是011111,与之后就是000000,最后一个1就没了。这个B选项其实就是lowbit操作。

不定项题

T1.NOIP初赛中,选手可以带入考场的有

A.笔

B.橡皮

C.手机(关机)

D.草稿纸

答案:AB

详见CCF官方规则。一般是不允许带手机和草稿纸,各地规定不太一样呢。

upd:附上官方规则的地址,本题考得是第12条。

选手进入考场时,只许携带笔、橡皮等非电子文具入场。禁止携带任何电子产品或机器设备入场,无存储功能的手表除外;手机(关机)、U盘或移动硬盘、键盘、鼠标、闹钟、计算器、书籍、草稿纸及背包等物品必须存放在考场外。如有违规带入的,一经发现,NOI各省特派员可直接取消违规选手的参赛资格。

T2.2-3树是一种特殊的树,它满足两个条件:

  1. 每个内部节点有两个或三个子节点;
  2. 所有的叶子节点到根的路径长度相同。

如果一棵2-3树有10个叶节点,那么它可能有?个非叶节点。

A.5

B.6

C.7

D.8

答案:CD

考虑每一层的节点数是1->2->5->10和1->2->4->10的形式。

T3.下列关于最短路算法的说法正确的有

A.当图中不存在负权回路但是存在负权边时,Dijkstra算法不一定能求出源点到所有点的最短路。

B.当图中不存在负权边时,调动多次Dijkstra算法能求出每对顶点间最短路径。

C.图中存在负权回路时,调用一次Dijkstra算法也一定能求出源点到所有点的最短路。

D.当图中不存在负权边时,调用一次Dijkstra算法不能用于每对顶点间的最短路计算。

答案:ABD

Dijkstra:单源最短路,不支持负权边。当然负权回路也是不行的

T4.下列说法中,是树的性质的有

A.无环

B.任意两个节点之间有且只有一条简单路径

C.有且只有一个简单环

D.边的数目恰好是顶点数目-1

答案:ABD

树的性质常识题。

T5.下列关于图灵奖的说法中,正确的有

A.图灵奖是由电气和电子工程师协会(IEEE)设立的。

B.目前获得该奖项的华人学者只有姚期智教授衽。

C.其名称取自计算机科学的先驱、英国科学家艾伦·麦席森·图灵。

D.它是计算机界最负盛名、最崇高的一个奖项,有“计算机界的诺贝尔奖”之称。

答案:BCD

图灵奖是美国的ACM协会创办的。

问题求解

T1.甲乙丙丁四人在考虑周末要不要外出郊游。

已知

  1. 如果周末下雨,并且乙不去,则甲一定不去;
  2. 如果乙去,则丁一定去;
  3. 如果丙去,则丁一定不去;
  4. 如果丁不去,而且甲不去,则丙一定不去。

如果周末丙去了,则甲(去了/没去),乙(去了/没去),丁(去了/没去),周末(下雨、没下雨)。

答案:去了,没去,没去,没下雨

根据3,丙去了,那么丁没去

根据2的逆否,丁没去,乙一定没去

根据4,丙去了,丁没去,那么甲一定去了//upd于12.13

根据1,乙没去,甲去了,周末不下雨

T2.方程\(a*b=(a\ \mathrm{or}\ b)*(a\ \mathrm{and}\ b)\),在a和b都取[0,31]中的整数时,共有?组解。(*表示乘法;or表示按位或运算;and表示按位与运算)

答案:454

介绍一个结论:\(a\ \mathrm{and}\ b\le\min(a,b)\le\max(a,b)\le a\ \mathrm{or}\ b<2*\max(a,b)\)

最后一个小于号可能不太理解,因为乘以一个2一定要进位,a or b一定是不会进位的。前面的不等号很好理解

那么对答案的贡献形式一定是\(\left\{\begin{aligned}a\ \mathrm{and}\ b=\min(a,b)\\a\ \mathrm{or}\ b=\max(a,b)\end{aligned}\right.\)。那么最小值的二进制一定是最大值的二进制的子集。枚举所有二进制可能的位数,由于要删去\(a=b\)的重复情况,那么答案为\(\displaystyle2\times\left(\sum_{i=0}^5\mathrm{C}_{5}^i\times2^i\right)-32=454\)

阅读程序写结果

程序自己打的,大括号换了行否则太不顺眼了。。。

  1. #include <cstdio>
  2. int main()
  3. {
  4. int x;
  5. scanf("%d", &x);
  6. int res = 0;
  7. for (int i = 0; i < x; ++i)
  8. {
  9. if (i * i % x == 1)
  10. {
  11. ++res;
  12. }
  13. }
  14. printf("%d", res);
  15. return 0;
  16. }

输入:15

输出:4

打表找0到14中所有数平方对15取模判断是否为1即可,最后是1,4,11,14是答案。建议验算几遍,以免出错。

  1. #include <cstdio>
  2. int n, d[100];
  3. bool v[100];
  4. int main()
  5. {
  6. scanf("%d", &n);
  7. for (int i = 0; i < n; ++i)
  8. {
  9. scanf("%d", d + i);
  10. v[i] = false;
  11. }
  12. int cnt = 0;
  13. for (int i = 0; i < n; ++i)
  14. {
  15. if (!v[i])
  16. {
  17. for (int j = i; !v[j]; j = d[j])
  18. {
  19. v[j] = true;
  20. }
  21. ++cnt;
  22. }
  23. }
  24. printf("%d\n", cnt);
  25. return 0;
  26. }

输入:10 7 1 4 3 2 5 9 8 0 6

输出:6

置换的阶的计数。我tm一开始看成11个元素的置换了,把开头的10也算进去了算成了3。这个动手模拟很简单的。

  1. #include <iostream>
  2. using namespace std;
  3. string s;
  4. long long magic(int l, int r)
  5. {
  6. long long ans = 0;
  7. for (int i = l; i <= r; ++i)
  8. {
  9. ans = ans * 4 + s[i] - 'a' + 1;
  10. }
  11. return ans;
  12. }
  13. int main()
  14. {
  15. cin >> s;
  16. int len = s.length();
  17. int ans = 0;
  18. for (int l1 = 0; l1 < len; ++l1)
  19. {
  20. for (int r1 = l1; r1 < len; ++r1)
  21. {
  22. bool bo = true;
  23. for (int l2 = 0; l2 < len; ++l2)
  24. {
  25. for (int r2 = l2; r2 < len; ++r2)
  26. {
  27. if (magic(l1, r1) == magic(l2, r2) && (l1 != l2 || r1 != r2))
  28. {
  29. bo = false;
  30. }
  31. }
  32. }
  33. if (bo)
  34. {
  35. ans += 1;
  36. }
  37. }
  38. }
  39. cout << ans << endl;
  40. return 0;
  41. }

输入:abacaba

输出:16

寻找字符串中独一无二的子串的个数。magic函数其实是[l,r]区间内的一个BKDRHash。什么鬼名字。话说CCF的程序效率太低了吧

  1. #include <cstdio>
  2. using namespace std;
  3. const int N = 110;
  4. bool isUse[N];
  5. int n, t;
  6. int a[N], b[N];
  7. bool isSmall()
  8. {
  9. for (int i = 1; i <= n; ++i)
  10. if (a[i] != b[i]) return a[i] < b[i];
  11. return false;
  12. }
  13. bool getPermutation(int pos)
  14. {
  15. if (pos > n)
  16. {
  17. return isSmall();
  18. }
  19. for (int i = 1; i <= n; ++i)
  20. {
  21. if (!isUse[i])
  22. {
  23. b[pos] = i; isUse[i] = true;
  24. if (getPermutation(pos + 1))
  25. {
  26. return true;
  27. }
  28. isUse[i] = false;
  29. }
  30. }
  31. return false;
  32. }
  33. void getNext()
  34. {
  35. for (int i = 1; i <= n; ++i)
  36. {
  37. isUse[i] = false;
  38. }
  39. getPermutation(1);
  40. for (int i = 1; i <= n; ++i)
  41. {
  42. a[i] = b[i];
  43. }
  44. }
  45. int main()
  46. {
  47. scanf("%d%d", &n, &t);
  48. for (int i = 1; i <= n; ++i)
  49. {
  50. scanf("%d", &a[i]);
  51. }
  52. for (int i = 1; i <= t; ++i)
  53. {
  54. getNext();
  55. }
  56. for (int i = 1; i <= n; ++i)
  57. {
  58. printf("%d", a[i]);
  59. if (i == n) putchar('\n'); else putchar(' ');
  60. }
  61. return 0;
  62. }

输入1:6 10 1 6 4 5 3 2

输出1:2 1 3 5 6 4

输入2:6 200 1 5 3 4 2 6

输出2:3 2 5 6 1 4

不难看出本题是求排列的下t个排列,CCF这个程序实现的效率太菜了吧,竟然从初始排列不断枚举,直到排列大于给定排列。

对于输入1,可以直接手推

对于输入2,正解应该是康托展开(了解一下),但是也可以一次跳阶乘次步。例如当后3位是单调递减的时候,可以直接跳3的阶乘次步,直接转移到下一个后3位是单调递减的情况。能节省中间模拟的时间,这种方法对不会康托展开的同学(比如我)适用

完善程序

T1.对于一个1到n的排列P(即1到n中每一个数在P中出现了恰好一次),令\(q_i\)为第i个位置之后第一个比\(P_i\)值更大的位置,如果不存在这样的位置,则\(q_i=n+1\)。举例来说,如果n=5且P为1 5 4 2 3,则q为2 6 6 5 6。

下列程序读入了排列P,使用双向链表求解了答案。试补全程序。(第二空2分,其余3分)

数据范围\(1\le n\le10^5\)。

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 100010;
  4. int n;
  5. int L[N], R[N], a[N];
  6. int main()
  7. {
  8. cin >> n;
  9. for (int i = 1; i <= n; ++i)
  10. {
  11. int x;
  12. cin >> x;
  13. ____(1)____;//a[x] = i
  14. }
  15. for (int i = 1; i <= n; ++i)
  16. {
  17. R[i] = ____(2)____;//i + 1
  18. L[i] = i - 1;
  19. }
  20. for (int i = 1; i <= n; ++i)
  21. {
  22. L[____(3)____] = L[a[i]];//R[a[i]]
  23. R[L[a[i]]] = R[____(4)____];//a[i]
  24. }
  25. for (int i = 1; i <= n; ++i)
  26. {
  27. cout << ____(5)____ << " ";//R[i]
  28. }
  29. cout << endl;
  30. return 0;
  31. }

1.a[i]表示大小为i的元素所在位置。

2.对称地写下一行的东西。链表的下一个元素。

3.对称地写下一行的东西。删除链表中本元素,把本元素右边元素的左指针跨过本元素指向左侧元素。

4.还是对称。把左边元素右指针指向右侧元素。

5.输出第i个数的后继元素即第一个比他大的元素,即R[i]。

T2.一只小猪要买N件物品(N不超过1000)。

它要买的所有商品在两家商店里都有卖。第i件物品在第一家商店的价格是a[i],在第二家商店的价格是b[i],两个价格都不小于0且不超过10000。如果在第一家商店买的物品的总额不少于50000,那么在第一家店买的物品都可以打95折(价格变为原来的0.95倍)。

求小猪买齐所有物品所需最小的总额。

输入:第一行一个数N。接下来N行,每行两个数。第i行的两个数分别代表a[i],b[i]。

输出:输出一行一个数,表示最少需要的总额,保留两位小数。

试补全程序。(第一空2分,其余3分)

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int Inf = 1000000000;
  5. const int threshold = 50000;
  6. const int maxn = 1000;
  7. int n, a[maxn], b[maxn];
  8. bool put_a[maxn];
  9. int total_a, total_b;
  10. double ans;
  11. int f[threshold];
  12. int main()
  13. {
  14. scanf("%d", &n);
  15. total_a = total_b = 0;
  16. for (int i = 0; i < n; ++i)
  17. {
  18. scanf("%d%d", a + i, b + i);
  19. if (a[i] <= b[i]) total_a += a[i];
  20. else total_b += b[i];
  21. }
  22. ans = total_a + total_b;
  23. total_a = total_b = 0;
  24. for (int i = 0; i < n; ++i)
  25. {
  26. if (____(1)____)//0.95 * a[i] <= b[i]
  27. {
  28. put_a[i] = true;
  29. total_a += a[i];
  30. }
  31. else
  32. {
  33. put_a[i] = false;
  34. total_b += b[i];
  35. }
  36. }
  37. if (____(2)____)//total_a >= threshold
  38. {
  39. printf("%.2f", total_a * 0.95 + total_b);
  40. return 0;
  41. }
  42. f[0] = 0;
  43. for (int i = 1; i < threshold; ++i)
  44. f[i] = Inf;
  45. int total_b_prefix = 0;
  46. for (int i = 0; i < n; ++i)
  47. {
  48. if (!put_a[i])
  49. {
  50. total_b_prefix += b[i];
  51. for (int j = threshold - 1; j >= 0; --j)
  52. {
  53. if (____(3)____ >= threshold && f[j] != Inf)//total_a + j + a[i]
  54. ans = min(ans, (total_a + j + a[i]) * 0.95 + ____(4)____);//f[j] + total_b - total_b_prefix
  55. f[j] = min(f[j] + b[i], j >= a[i] ? ____(5)____ : Inf);//f[j - a[i]]
  56. }
  57. }
  58. }
  59. printf("%.2f", ans);
  60. return 0;
  61. }

一个奇怪的DP。

1.如果是a[i]<=b[i],那么要上面的统计有啥用。这里的循环其实是在假定需要打折的情况下,先挑选已经钦定的a[i]的物品。

2.判断如果打折,直接购买便宜的a是否已经ok了。如果是就不需要再舍弃b购买一个较贵的a了,直接输出即可。

3.注意到下面是total_a + j + a[i]乘的0.95,那么这个一定是a的总价,那么它一定要大于等于50000。

4.观察下面的min,f[j]+b[i]说明f数组记录的是和b的价格有关的,而且它必须要出现,那么就放到这里。注意到total_b_prefix和total_b没有用过,说明他俩必须要用上,由于prefix是前缀,所以让total_b减去total_b_prefix即可。

5.由于j>=a[i],那么j-a[i]>=0,考虑我们的背包转移,可以大胆猜想这里填f[j-a[i]]。

本题实际上的状态是f[j]代表在前i个物品中,购买a店物品j元情况下购买b店物品的最小价值。total_a+j+a[i]代表买所有钦定要买的+额外需要买的+这次买的,f[j]+total_b-total_b_prefix是指i到n中所有选b,前面按照f[j]的状态取,b的价格。最后f[j]和取这次的b[i]与从j-a[i]转移过来去一个min,表示j这个状态取b还是取a。


总结:这次考试我拿了95分,总体来说题和去年水平差不多,这套题还是比较注重思维能力吧,当然不少了CCF颂歌题,“常识”题。希望大家参加NOIP2018复赛时候RP++吧。

NOIP2018初赛总结(提高组)(试题+答案+简要解析)的更多相关文章

  1. NOIP2018初赛题解 提高组

  2. NOIp 2018 普及&提高组试题答案

    你们考的咋样呢?在评论区说出自己的分数吧!

  3. 疫情控制 2012年NOIP全国联赛提高组(二分答案+贪心)

    P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...

  4. NOIP 2018 提高组初赛试题 题目+答案+简要解析

    一.单项选择题(共 10  题,每题 2  分,共计 20  分: 每题有且仅有一个正确选项)       1. 下列四个不同进制的数中,与其它三项数值上不相等的是( ). A. (269) 16 B ...

  5. noip2010初赛提高组 试题详解

    转载自:https://blog.csdn.net/eirlys_north/article/details/52889970 一.单项选择题 1.与16进制数 A1.2等值的10进制数是 ( ) A ...

  6. noip2011初赛提高组 试题详解

    转载自:https://blog.csdn.net/Eirlys_North/article/details/52889993 一.单项选择题(共20题,每题1.5分,共计30分,每题有且仅有一个正确 ...

  7. NOIP2016初赛总结(提高组)

    题目:https://www.zhihu.com/question/51865837/answer/127892121 注:我是HE的,不是JS的,照片是ZYJ神犇的 单选 一.单项选择题(共15 题 ...

  8. 2016年第七届蓝桥杯javaB组 试题 答案 解析

    1.煤球数目 有一堆煤球,堆成三角棱锥形.具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), .... 如果一共有100层,共有多少个煤 ...

  9. 2015年第六届蓝桥杯javaB组 试题 答案 解析

    1.三角形面积 如图1所示.图中的所有小方格面积都是1. 那么,图中的三角形面积应该是多少呢? 请填写三角形的面积.不要填写任何多余内容或说明性文字. ##### 答案 : 28   ### 2.立方 ...

随机推荐

  1. throw和throws的区别和联系

    突然发现今天诗兴大发,看来又得写点内容了. throw和throws对于Java程序员而言它们真的不是很陌生.但对于我这样的选手而言一提到它们的区别和联系就蒙圈了... 为了以后不蒙圈,今天就研究一下 ...

  2. 基于mjpg-streamer网络视频服务器移植

    MJPG简介: MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名. MJPEG 全名为 "Motion Joint Photographic Experts Group&q ...

  3. python-xlrd api

    1.导入模块 import xlrd from xlrd import open_workbook 2.打开Excel文件读取数据 data = xlrd.open_workbook('excelFi ...

  4. PD中更改显示Name还是Code的设置

    菜单->Tool->Model Options->Name Convention->右侧display中选择显示name还是code. 此外,在16版中,还可以通过Tool-D ...

  5. PowerDesigner中CDM和PDM如何定义外键关系

    有A.B两张表(实体),各自有id作为主键,两表是一一对应关系.但略有不同: A表一条记录可以对应0或1条B表记录,B表一条记录必须对应唯一条A表记录. 这样的关系如何在CDM或PDM中定义? 在最后 ...

  6. php中的foreach改变数组的值的问题

    翻到PHP文档的foreach那页这样写道: “foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误 ...

  7. LAMP 2.4 Apache访问控制

    通过查看日志发现有个IP 恶意攻击你的网址,可以控制这个IP的访问. 打开主配置文件复制模板. vim /usr/local/apache2/conf/httpd.conf 搜索 /Order 复制 ...

  8. elmah数据库sql脚本

    /* 错误管理工具 SQL代码 */CREATE TABLE dbo.ELMAH_Error( ErrorId UNIQUEIDENTIFIER NOT NULL, Application NVARC ...

  9. Tornado之抽屉实战(2)--数据库表设计

    经过我们上次分析,数据库要有最基本的四张表,用户表,消息表,类型表,点赞表,评论表,接下来我们看着怎么设计吧 首先我们要清楚,表设计的代码是写在models下的 用户表 ? 1 2 3 4 5 6 7 ...

  10. Codeforces 1077(F1+F2) DP 单调队列

    题意:给你一个n个元素的数组,从中选取x个元素,并且要保证任意的m个位置中必须至少有一个元素被选中,问选中元素的和最大可以是多少? F1 n,m,x到200 F2 n,m,x到5000. 思路1:设d ...