OI 入门自测

OI入门自测


author: GGN_2015 Date: 2020-07-13

    _    _____ ___               _    _                         
   / \  |  ___/ _ \   _____     / \  | |_      ____ _ _   _ ___ 
  / _ \ | |_ | | | | |_____|   / _ \ | \ \ /\ / / _` | | | / __|
 / ___ \|  _|| |_| | |_____|  / ___ \| |\ V  V / (_| | |_| \__ \
/_/   \_\_|   \___/          /_/   \_\_| \_/\_/ \__,_|\__, |___/
                                                      |___/     
 _____ _                _                        ___ ___ 
|  ___(_)_ __ _ __ ___ | |_   _    ___  _ __    / _ \_ _|
| |_  | | '__| '_ ` _ \| | | | |  / _ \| '_ \  | | | | | 
|  _| | | |  | | | | | | | |_| | | (_) | | | | | |_| | | 
|_|   |_|_|  |_| |_| |_|_|\__, |  \___/|_| |_|  \___/___|
                          |___/                          

以下题目不必全部完成,仅用于自测。下述题目中涉及程序设计的题目,若无特殊声明,则其时间限制为 1000ms,空间限制为 512MB。

卷一:NOIP-J 的相关内容

关于学习背景

我们希望了解以下你的OI学习历程,请回答以下问题:

  1. 你为什么要学习OI.
  2. 你从何时开始接触C++编程?
  3. 到目前为止你大致学习了哪些算法?
  4. 到目前为之你大致完成了多少道OI题目?
  5. 比较右侧两者,你觉得你更倾向于哪一者?A.学习算法并把算法将给身边的人,B.学习算法并独自钻研刷题

关于排序

  1. 你会使用C++STL提供的sort吗?如果会,请编写一个程序,解决下述问题,并将该程序命名为"sort.cpp"

描述

期中考试结束了,你拿到了全校N名学生的语文、数学及英语成绩。老师希望你能将这些同学的学号按照以下规则拍成一列:对于总分不同的两个同学A和B,若A的总分高于B的总分,那么A同学应被排在B同学之前。对于总分相同但语文成绩不同的两个同学A和B,若A的语文成绩高于B的语文成绩,那么A同学应被排在B同学之前。对于总分相同且语文成绩相同但数学成绩不同的两个同学A和B,若A的数学成绩高于B的数学成绩,那么A同学应被排在B同学之前。同理,对于总分相同、语文、数学成绩均对应相同,但英语成绩不同的两名同学A和B,若A的英语成绩高于B,那么A同学应被排在B同学之前。对于总分相同,语文数学英语成绩均对应相同的两名同学A和B,若A的学号小于B的学号,那么A应被排在B的前面。

简述

已知N名同学的学号、语文成绩、数学成绩和英语成绩,请以总分为第一关键字,语文成绩为第二关键字,数学成绩为第三关键字,英语成绩为第四关键字从大至小排序。若两名同学成绩完全相同,则将学号小的排在前面。

输入

从同文件夹下文件"sort.in"输入
第1行,一个整数N
第 2 ~ N + 1 N+1 N+1 行每行三个整数
1 + i   ( 1 ≤ i ≤ N ) 1+i\space (1\leq i \leq N) 1+i (1iN) 行 的三个整数 A i , B i , C i A_i, B_i, C_i Ai,Bi,Ci 分别表示学号为i的同学的语文成绩,数学成绩及英语成绩,相邻的两个数之间用一个空格隔开

输出

向同文件夹下文件"sort.out"输出
一行,N个整数
其中第i个数 n i n_i ni表示表示按要求排列后排在第i位的同学的学号

样例

sort.in

3
100 90 80
90 100 80
100 80 90

sort.out 应为

1 3 2

约定

1 ≤ N ≤ 1 0 6 ; 0 ≤ A i , B i , C i ≤ 100 ; N , A i , B i , C i ∈ Z 1 \leq N \leq 10^6; 0 \leq A_i, B_i, C_i \leq 100; N,A_i,B_i,C_i\in \Z 1N106;0Ai,Bi,Ci100;N,Ai,Bi,CiZ

附加题

若题面不变,将数据范围改为:
1 ≤ N ≤ 1 0 7 ; 0 ≤ A i , B i , C i ≤ 100 ; N , A i , B i , C i ∈ Z 1 \leq N \leq 10^7; 0 \leq A_i, B_i, C_i \leq 100; N,A_i,B_i,C_i\in \Z 1N107;0Ai,Bi,Ci100;N,Ai,Bi,CiZ
你有什么方法在1秒内解决这个问题吗。

  1. 请简述一下归并排序的排序原理,并简要证明其时间复杂度。

关于图

  1. 请你分别描述一下临界矩阵、临界表、前向星都是如何记录一张有向图的,用这些方法有什么优劣。
  2. 请你设计一个算法,计算一个无向图中某一结点V所在的连通块的大小。
  3. 如果你学习过广度有限搜索(BFS)这一算法,那么请你完成这样一个题目,并将你的程序命名为"maze.cpp"。

背景

你在一个迷宫中,迷宫中有一个出口和若干个火源。迷宫可以视为一个二维网格,每经过一个单位时间,你可以从当前所在的位置移动到位于当前位置上、下、左、右且与当前位置相邻的四个格子中(但你不能走到网格的边界之外)。同时,每经历一个单位时间,火势会从一个着火的格子蔓延到位于该格子上下左右且与之相邻的四个格子中(该格子自身的火并不熄灭)。地图中一部分格子被墙所占据,一部分格子是空地,而无论哪一时刻,你都不能位于一个着火的格子中,且你不能“穿墙而过”(即走到一个被墙占据的格子)。需要注意的是,火只能在空地之间蔓延,也就是说墙不会被火点燃。给出地图的尺寸、地图中墙和空地的位置,你的初始位置、出口的位置、火源的个数以及每个火源的位置(火源即初始时刻就被火占据的格子),请你编写一个程序,判断你能否走到出口。

输入

从同文件夹下的文件"maze.in"输入
第一行,一个整数N,表示该迷宫可以表示为一个 N × N N\times N N×N的网格图,网格图中每个位置可用一个坐标(x, y)表示,且 1 ≤ x , y ≤ N 1\leq x, y \leq N 1x,yN
第2~N+1行,每行N个整数。
1 + i   ( 1 ≤ i ≤ N ) 1+i\space(1\leq i\leq N) 1+i (1iN)行,的第 j j j个整数 A i , j A_{i,j} Ai,j有五种可能的取值。

A i , j = 0 A_{i,j} = 0 Ai,j=0 表示x=i, y=j所对应的格子为空地。
A i , j = 1 A_{i,j} = 1 Ai,j=1 表示x=i, y=j所对应的格子为墙。
A i , j = 2 A_{i,j} = 2 Ai,j=2 表示x=i, y=j所对应的格子为火源。
A i , j = 3 A_{i,j} = 3 Ai,j=3 表示x=i, y=j所对应的格子为你的初始位置,数据保证这样的位置只有一个。
A i , j = 4 A_{i,j} = 4 Ai,j=4 表示x=i, y=j所对应的格子为迷宫的出口,数据保证这样的位置只有一个。注意,火势可以蔓延到出口,火势蔓延到出口后,你将无法到达出口。

输出

向同文件夹下的文件"maze.out"输出
输出一行,一个字符串。
如果你能走到出口,输出一个字符串"yes",否则输出一个字符串“no”(不含双引号)。

样例

maze.in

6
1 1 1 1 1 1
1 0 0 0 0 1
1 0 1 4 0 1
1 0 3 1 0 1
1 0 0 0 0 1
1 2 1 1 1 1

maze.out 应为

yes

约定

1 ≤ N ≤ 10 1\leq N\leq 10 1N10

  1. 你听说过八皇后问题吗?请你简单描述一下什么是八皇后问题,并简述解决八皇后问题的算法。

关于动态规划

1.解决最长上升子序列问题,完成以下一道题目,并将程序命名为"lis.cpp"。

背景

给出一个长度为N的数列,找到其中所有上升子序列中最长的一个。
如果你不清楚什么是自序列,请看定义:

  1. S = < A 1 , A 2 , . . . , A N > S= S=<A1,A2,...,AN>是一个长度为N的数列,数列 < A i > ( 1 ≤ i ≤ N ) (1\leq i \leq N) <Ai>(1iN)为序列S的长度为1的子序列。
  2. S = < A 1 , A 2 , . . . , A N > S= S=<A1,A2,...,AN>是一个长度为N的数列, T = < B 1 , B 2 , . . . B M > T= T=<B1,B2,...BM>是一个长度为M的数列,且 ∀ 1 ≤ i ≤ M − 1 , 都 有 1 ≤ B i < B i + 1 ≤ N \forall 1 \leq i \leq M-1, 都有1\leq B_i1iM1,1Bi<Bi+1N,那么数列 < A B 1 , A B 2 , . . . A B M > <AB1,AB2,...ABM>则为数列S的长度为M的子序列。
  3. 通俗地说,在一个数列中删去零项或若干项,不改变剩余的数的顺序,依次排列得到的新数列,成为原数列的一个子序列。

输入

第一行,一个整数N,表示原数列中数的个数。
第二行,N个整数,其中第i个数 A i A_i Ai表示原数列中第i个位置上的数。

输出

一行,一个整数,表示最长上升子序列的长度。

样例

lis.in

9
9 3 6 4 8 2 3 1 5

lis.out 应为

3

约定

1 ≤ N ≤ 3000 , − 2 31 ≤ A i ≤ 2 31 − 1 1 \leq N \leq 3000,-2^{31} \leq A_i \leq 2^{31}-1 1N3000,231Ai2311

附加题

题面不变,数据范围改为:
1 ≤ N ≤ 1 0 6 , − 2 63 ≤ A i ≤ 2 63 − 1 1 \leq N \leq 10^6,-2^{63} \leq A_i \leq 2^{63}-1 1N106,263Ai2631

  1. 你了解01背包问题吗?请简述01背包问题并简述解决算法。
  2. 请解决这样一个问题,你不必写程序,但要简述算法思想:

背景

你有一个容积为V的背包,和N种物品。其中,对于第i种物品,每个物品的价值为 v i v_i vi,每个物品占据体积为 c i c_i ci,这种物品总共有 k i k_i ki个。
请从这些物品中取出若干件物品放入背包中,并使让背包中每个物品的价值之和最大,但占据的体积之和小于等于背包的容积V。

输入

第一行,两个整数,V,N,分别表示背包的容积,和物品的总数。
第二行,N个整数,其中第i个整数为 v i v_i vi,表示每个第i种物品的价值。
第三行,N个整数,其中第i个整数为 c i c_i ci,表示每个第i种物品占据的体积。
第四行,N个整数,其中第i个整数为 k i k_i ki,表示第i种物品的数量。

输出

一行,一个整数,表示在不超过背包容积的前提下,背包中物品价值和的最大值。

约定

1 ≤ V , N ≤ 1000 , 1 ≤ v i , c i , k i ≤ 1000 1\leq V,N \leq 1000, 1\leq v_i, c_i, k_i \leq 1000 1V,N1000,1vi,ci,ki1000

一些其他的问题

  1. 设计一个算法计算 2 N m o d    1 0 5 2^N \mod 10^5 2Nmod105,其中 1 ≤ N ≤ 1 0 18 1\leq N \leq 10^{18} 1N1018
  2. 你是否学习过最小生成树相关的算法,如果你学习过请你回答下述问题。

给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。题目保证有解。
多大的数据范围你能接受?
你能否接受 N ≤ 50000 , E ≤ 100000 N\leq 50000, E\leq100000 N50000,E100000

你可能感兴趣的:(算法导论,C++语言,数学,算法)