#CSPJCSMN02. 普及组程序专项02

普及组程序专项02

初赛程序题专项(二)

二、阅读程序

(1)

01 #include <iostream>
02
03 using namespace std;
04
05 int f(int x) {
06     if (x == 1) return 1;
07     int count = 0;
08     for (int i = 1; i * i <= x; ++i) {
09         if (x % i == 0) {
10             count++;
11             if (i * i != x) {
12                 count++;
13             }
14         }
15     }
16     return count;
17 }
18
19 int main() {
20     int n;
21     cin >> n;
22     long long total_sum = 0;
23     for (int i = 1; i <= n; ++i) {
24         total_sum += f(i);
25     }
26     cout << total_sum << endl;
27     return 0;
28 }

判断题

  1. 函数 f(x) 用于计算 x 的所有质因数的个数。 ( )
  2. 若输入 n6,则 f(6) 的返回值为 4。 ( )
  3. 将第 08 行的 i * i <= x 修改为 i <= x / i,程序的时空复杂度和输出结果均不受影响。 ( )

选择题

  1. 该程序的功能是 ( )。

    • A. 计算从 1 到 n 所有数的质因数总和
    • B. 计算从 1 到 n 所有数的约数个数总和
    • C. 计算从 1 到 n 所有完数的个数
    • D. 计算从 1 到 n 所有质数的个数
  2. 若输入 n10,则输出为 ( )。

    • A. 23
    • B. 25
    • C. 27
    • D. 30

(2)

01 #include <iostream>
02 #include <vector>
03 #include <algorithm>
04
05 using namespace std;
06
07 vector<vector<int>> adj;
08 pair<int, int> result; // {distance, node}
09
10 void dfs(int u, int p, int d) {
11     if (d > result.first) {
12         result = {d, u};
13     }
14     for (int v : adj[u]) {
15         if (v != p) {
16             dfs(v, u, d + 1);
17         }
18     }
19 }
20
21 int main() {
22     int n;
23     cin >> n;
24     adj.resize(n + 1);
25     for (int i = 0; i < n - 1; ++i) {
26         int u, v;
27         cin >> u >> v;
28         adj[u].push_back(v);
29         adj[v].push_back(u);
30     }
31
32     result = {-1, -1};
33     dfs(1, 0, 0);
34
35     int endpoint = result.second;
36     result = {-1, -1};
37     dfs(endpoint, 0, 0);
38
39     cout << result.first << endl;
40
41     return 0;
42 }

判断题

  1. 该程序输入的 n-1 行数据,描述的是一个无向图的邻接表。 ( )
  2. 程序中的 p 参数在 dfs 函数中是为了防止在树的遍历中走回头路(即从子节点返回父节点)。 ( )
  3. 如果只执行一次 dfs (即删除第 35-37 行),程序对于所有输入,输出都将减半。 ( )

选择题

  1. 该程序计算的是 ( )。

    • A. 图的最小生成树的边权和
    • B. 从节点 1 出发的最长路径长度
    • C. 树的直径
    • D. 树的重心
  2. 若输入为:

    7
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    

    则输出为 ( )。

    • A. 3
    • B. 4
    • C. 5
    • D. 6

(3)

01 #include <iostream>
02 #include <vector>
03 #include <algorithm>
04
05 using namespace std;
06
07 int main() {
08     int n;
09     cin >> n;
10     vector<int> a(n);
11     for (int i = 0; i < n; ++i) {
12         cin >> a[i];
13     }
14
15     if (n == 0) {
16         cout << 0 << endl;
17         return 0;
18     }
19
20     vector<int> dp(n);
21     dp[0] = a[0];
22     int max_ans = dp[0];
23
24     for (int i = 1; i < n; ++i) {
25         dp[i] = max(a[i], dp[i - 1] + a[i]);
26         max_ans = max(max_ans, dp[i]);
27     }
28
29     cout << max_ans << endl;
30     return 0;
31 }

判断题

  1. dp[i] 的含义是:在数组 a 的前 i+1 个元素(a[0]a[i])中,任意子数组的最大和。 ( )
  2. 如果输入数组 a 的所有元素均为负数,程序的输出结果一定等于数组 a 中的最大元素。 ( )
  3. 该程序的时间复杂度和空间复杂度均为 O(n)。 ( )

选择题

  1. 该程序解决的问题是 ( )。

    • A. 最长上升子序列
    • B. 寻找数组中第 k 大的元素
    • C. 最大子数组和
    • D. 数组元素总和
  2. 如果将第 25 行的 dp[i] = max(a[i], dp[i - 1] + a[i]); 改为 dp[i] = dp[i-1] + a[i];,并且输入为 5-1 -2 5 -1 -2,则输出会 ( )。

    • A. 不变
    • B. 从 5 变为 -1
    • C. 从 5 变为 2
    • D. 发生运行时错误

三、完善程序

(1) 乘船问题

题目描述:n 个人,第 i 个人的重量为 w[i]。每艘船的最大载重量为 limit,且最多只能坐两个人。求最少需要多少艘船才能将所有人带走。

01 #include <iostream>
02 #include <vector>
03 #include <algorithm>
04
05 using namespace std;
06
07 int main() {
08     int n, limit;
09     cin >> n >> limit;
10     vector<int> w(n);
11     for (int i = 0; i < n; ++i) cin >> w[i];
12
13     sort(w.begin(), w.end());
14
15     int boats = 0;
16     int i = 0, j = ①;
17
18     while (②) {
19         boats++;
20         if (i < j && ③ <= limit) {
21             ④;
22         }
23         j--;
24     }
25
26     cout << boats << endl;
27     return 0;
28 }
  1. ①处应填 ( )。

    • A. 0
    • B. n
    • C. n - 1
    • D. i + 1
  2. ②处应填 ( )。

    • A. i < j
    • B. i <= j
    • C. i != j
    • D. boats < n
  3. ③处应填 ( )。

    • A. w[i]
    • B. w[j]
    • C. w[i] + w[j]
    • D. limit - w[j]
  4. ④处应填 ( )。

    • A. j--
    • B. i++
    • C. boats++
    • D. i = j

(2) 二维区域和

题目描述: 给定一个 n x m 的矩阵,有 q 次询问,每次询问一个子矩阵的元素之和。

01 #include <iostream>
02 #include <vector>
03
04 using namespace std;
05
06 int main() {
07     int n, m;
08     cin >> n >> m;
09     vector<vector<int>> a(n + 1, vector<int>(m + 1));
10     vector<vector<int>> s(n + 1, vector<int>(m + 1, 0));
11
12     for (int i = 1; i <= n; ++i) {
13         for (int j = 1; j <= m; ++j) {
14             cin >> a[i][j];
15             s[i][j] = s[i - 1][j] + ① - s[i - 1][j - 1] + a[i][j];
16         }
17     }
18
19     int q;
20     cin >> q;
21     while (q--) {
22         int x1, y1, x2, y2;
23         cin >> x1 >> y1 >> x2 >> y2;
24         int sum = s[x2][y2] - s[x1 - 1][y2] - ② + ③;
25         cout << sum << endl;
26     }
27
28     return 0;
29 }
  1. ①处应填 ( )。

    • A. s[i][j - 1]
    • B. s[i][j + 1]
    • C. a[i][j - 1]
    • D. s[i - 1][j]
  2. ②处应填 ( )。

    • A. s[x2][y1]
    • B. s[x1][y2]
    • C. s[x2][y1 - 1]
    • D. s[x1 - 1][y1]
  3. ③处应填 ( )。

    • A. s[x1][y1]
    • B. s[x1 - 1][y1 - 1]
    • C. a[x1][y1]
    • D. s[x2 - 1][y2 - 1]