#CSPJSH07. 珅泽教育CSP-J第一轮模拟考第七套

珅泽教育CSP-J第一轮模拟考第七套

一、单项选择题(共15题,每题2分,共计30分;每题有且仅有一个正确选项)

  1. 如果开始时计算机处于小写输入状态,现在有一只小老鼠反复按照 CapsLock、字母键 A、字母键 S 和字母键 D 的顺序循环按键,即
  • CapsLockASDCapsLockASD、……

则屏幕上输出的第 20252025 个字符是字母( )。

{{ select(1) }}

  • A
  • S
  • D
  • a
  1. 88 位二进制补码中,10101011 表示的是十进制下的( )。

{{ select(2) }}

  • 85-85
  • 43-43
  • 4343
  • 8585
  1. 给定一个含 NN 个不相同数字的数组,在最坏情况下,找出其中最大或最小的数,至少需要 N1N-1 次比较操作。则最坏情况下,在该数组中同时找最大与最小的数至少需要( )次比较操作。

 \lceil\ \rceil 表示向上取整, \lfloor\ \rfloor 表示向下取整)。

{{ select(3) }}

  • 3N22\left\lceil \frac{3N}{2} \right\rceil - 2
  • 3N22\left\lfloor \frac{3N}{2} \right\rfloor - 2
  • 2N22N - 2
  • 2N42N - 4
  1. 表达式 a(b+c)da * (b + c) - d 的后缀表达形式为( )。

{{ select(4) }}

  • abcd*+-
  • abc+*d-
  • abc*+d-
  • -+*abcd
  1. 约定二叉树的根节点高度为 11。一棵结点数为 20252025 的二叉树最少有( )个叶子结点;一棵结点数为 20252025 的二叉树最小的高度值是( )。

{{ select(5) }}

  • 1,111,11
  • 1,121,12
  • 2,112,11
  • 2,122,12
  1. 向一个栈顶指针为 hs 的链式栈中插入一个指针 s 指向的结点时,应执行( )。

A.

hs->next = s;

B.

s->next = hs;
hs = s;

C.

s->next = hs->next;
hs->next = s;

D.

s->next = hs;
hs = hs->next;

{{ select(6) }}

  • A
  • B
  • C
  • D
  1. 22-33 树是满足两个条件的树:
  • 所有叶结点到根的路径长度相同
  • 所有非叶子结点有两个或三个子结点

如果一棵 22-33 树有 1010 个叶结点,那么它可能有( )个非叶结点。

{{ select(7) }}

  • 33
  • 44
  • 66
  • 88
  1. 由四个没有区别的点构成的简单无向连通图的个数是( )。

{{ select(8) }}

  • 66
  • 77
  • 88
  • 99
  1. 设含有 1010 个元素的集合的全部子集数为 SS,其中由 77 个元素组成的子集数为 TT,则 TS\frac{T}{S} 的值( )。

{{ select(9) }}

  • 532\frac{5}{32}
  • 15128\frac{15}{128}
  • 18\frac{1}{8}
  • 21128\frac{21}{128}
  1. 如下图所示,共有 1313 个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由 1100,或由 0011)。现在要使得所有的格子中的数字都变为 00,至少需要( )次操作。

第10题格子图

{{ select(10) }}

  • 33
  • 44
  • 55
  • 66
  1. 一个 1×81 \times 8 的方格图形(不可旋转)用黑、白两种颜色填涂每个方格。如果每个方格只能填涂一种颜色,且不允许两个黑格相邻,共有( )种填涂方案。

{{ select(11) }}

  • 88
  • 5555
  • 5656
  • 6464
  1. GG 是有 nn 个结点、mm 条边(nmn \le m)的连通图,必须删去 GG 的( )条边,才能使得 GG 变成一棵树。

{{ select(12) }}

  • mn+1m-n+1
  • mnm-n
  • m+n+1m+n+1
  • nm+1n-m+1
  1. 77 个一模一样的苹果,放到 33 个一样的盘子中,一共有( )种放法。

{{ select(13) }}

  • 77
  • 88
  • 2121
  • 21872187
  1. f0=0,f1=1,fn+1=fn+fn12f_0=0, f_1=1, f_{n+1}=\frac{f_n+f_{n-1}}{2},则随着 ii 的增大,fif_i 将接近于( )。

{{ select(14) }}

  • 12\frac{1}{2}
  • 23\frac{2}{3}
  • 512\frac{\sqrt{5}-1}{2}
  • 11
  1. 以下是 3232 位机器和 6464 位机器的区别是( )。

{{ select(15) }}

  • 显示器不同
  • 硬盘大小不同
  • 寻址空间不同
  • 输入法不同

二、阅读程序(判断题正确填T,错误填F;判断题1分,选择题3分,共计40分)

第1题

int solve1(int n)
{
    n++;
    int size = 0;
    int digit[16];
    int pow = 1;
    int s = 0;
    while (n > 0) {
        digit[size] = n % 10;
        size++;
        n /= 10;
        s += pow;
        pow *= 5;
    }
    while (size > 0) {
        --size;
        pow /= 5;
        s += (digit[size] / 2) * pow;
        if (digit[size] % 2 == 0) break;
    }
    return s - 1;
}

int solve2(int n)
{
    int s = 0;
    for(int i = 1; i <= n ; i += 2)
    {
        int t = i;
        bool pass = true;
        while (t > 0) {
            int x = t % 10;
            if(x%2 == 0)
            {
                pass = false;
                break;
            }
            t /= 10;
        }
        if (pass) s++;
    }
    return s;
}

保证 solve1solve2 的参数 n 是非负整数。

  1. solve1(11) 的返回值为 6

{{ select(16) }}

  • 正确
  • 错误
  1. solve2(12345) 的返回值为 906

{{ select(17) }}

  • 正确
  • 错误
  1. 对所有的 n>0n > 0,必有 solve1(n) <= n

{{ select(18) }}

  • 正确
  • 错误
  1. solve1(0) 的返回值为 0

{{ select(19) }}

  • 正确
  • 错误
  1. 关于 solve1(n)solve2(n) 的大小关系,当 n0n \ge 0 时,下列说法正确的是( )。

{{ select(20) }}

  • 必然有 solve1(n) < solve2(n)
  • 必然有 solve1(n) == solve2(n)
  • 只有当 nn 为偶数时,才有 solve1(n) == solve2(n)
  • 只有当 nn 为奇数时,才有 solve1(n) == solve2(n)
  1. 若将 solve1 函数中第一句 n++ 去掉,将 solve2 函数中 for 循环的 i += 2 改为 i += 1,则新返回值与原来相比( )。

{{ select(21) }}

  • solve1 不变,solve2 变大
  • solve1 不变,solve2 变小
  • solve1 变小,solve2 不变
  • solve1 变大,solve2 不变
  1. solve1(n)solve2(n) 的时间复杂度为( )。

{{ select(22) }}

  • Θ(logn)\Theta(\log n)Θ(logn)\Theta(\log n)
  • Θ(logn)\Theta(\log n)Θ(n)\Theta(n)
  • Θ(logn)\Theta(\log n)Θ(nlogn)\Theta(n \log n)
  • Θ(n)\Theta(n)Θ(n2)\Theta(n^2)

第2题

int a[maxn];
int b[maxn];
int n, m;

const long long mod = 1'000'000'007;
bool filled[maxn][maxn];
long long mem[maxn][maxn];

long long solve(int i, int j)
{
    if (i == n) return 1;
    if (j == m) return 1;
    if (filled[i][j])
        return mem[i][j];
    filled[i][j] = true;

    long long sum = solve(i+1, j) + solve(i, j+1);
    if (a[i] == b[j]) {
        return mem[i][j] = sum % mod;
    }
    else {
        return mem[i][j] = (sum - solve(i+1, j+1)) % mod;
    }
}

int main()
{
    std::cin >> n >> m;
    for (int i = 0; i < n; ++i) std::cin >> a[i];
    for (int i = 0; i < m; ++i) std::cin >> b[i];
    std::cout << (solve(0, 0) + mod) % mod << "\n";
}
  1. 若依次输入数据 2 2 1 3 3 1,程序返回的结果是 3

{{ select(23) }}

  • 正确
  • 错误
  1. 如果 n = 0m = 0,程序返回的结果是 1

{{ select(24) }}

  • 正确
  • 错误
  1. 如果两个序列完全相同,程序返回的结果是 2n2^n

{{ select(25) }}

  • 正确
  • 错误
  1. 输出时,执行 solve(0, 0) + mod 是多余的运算。

{{ select(26) }}

  • 正确
  • 错误
  1. 该程序的主要功能是( )。

{{ select(27) }}

  • 计算两个序列的最长公共子序列的长度
  • 计算两个序列的公共子序列的数量
  • 计算两个序列的公共子串的数量
  • 计算两个序列的相同元素个数
  1. 该程序的时间复杂度为( )。

{{ select(28) }}

  • Θ(n+m)\Theta(n+m)
  • Θ(nm)\Theta(n \cdot m)
  • Θ(2m+n)\Theta(2^{m+n})
  • Θ(nlogm)\Theta(n \log m)
  1. a[i] != b[j] 时,返回值需要减去 solve(i+1, j+1) 的原因是( )。

{{ select(29) }}

  • 排除重复情况
  • 排除错误情况
  • 优化程序的空间效率
  • 优化程序的时间效率

第3题

long long k;
int n;
int p[20];
bool used[20] = {false};
long long frac[20];

void gen(int i)
{
    if (i > n)
    {
        for (int i = 1; i <= n; ++i) std::cout << p[i] << " ";
        return;
    }

    for (int a = 1; a <= n; ++a)
        if (not used[a]) {
            if (k <= frac[n-i]) {
                p[i] = a;
                used[a] = true;
                gen(i+1);
                return;
            }
            else {
                k -= frac[n-i];
            }
        }
}

int main()
{
    n = 1;
    frac[0] = frac[1] = 1;
    std::cin >> k;
    while (k > frac[n]) {
        k -= frac[n];
        frac[n+1] = frac[n] * (n+1);
        n++;
    }
    gen(1);
}
  1. 当输入 k1 时候,输出 1

{{ select(30) }}

  • 正确
  • 错误
  1. 当输入 k1000 时候,输出 1 5 2 4 3

{{ select(31) }}

  • 正确
  • 错误
  1. 关于程序输出的序列所满足的性质,错误的是( )。

{{ select(32) }}

  • 输出的每个数字各不相同
  • 输出的数字都在 1n 之间
  • 输出的相邻的数字差距不会超过 11
  • 最先输出的数字在程序中是最先被确定的。
  1. 下列说法正确的是( )。

{{ select(33) }}

  • 越大的 kk 一定会输出越长的序列
  • kk 若是奇数,输出序列的长度一定也是奇数
  • 程序的时间复杂度为 Θ(k!)\Theta(k!)
  • gen 递归是树形递归
  1. 若程序输出的第一个数字为 2,第二数字为 4,剩下还有三个数字,则输入的 k( )。

{{ select(34) }}

  • 最小值是 6060,最大值是 6565
  • 最小值是 6565,最大值是 7070
  • 最小值是 7070,最大值是 7575
  • 最小值是 7575,最大值是 8080
  1. 如果使得输出序列出现 7,则输入 k 最少需要( )。

{{ select(35) }}

  • 343343
  • 874874
  • 21702170
  • 50405040

三、完善程序(单选题,每小题3分,共计30分)

第1题

有一个用户,在连续的 nn 天里,都会收到积分,也会消费积分。积分在获得后的 mm 天内有效(mm 为一个给定的整数),过期失效。

在第 ii 天,用户将会获得 pip_i 分,他需要消费 cic_i 分。若积分不足,则用掉全部积分后用其他方式消费。消费积分时,先用最早的。当天获取的积分可以当天消费。请计算这个用户一共消费了多少积分。

const int max_size = 100000;
int queue[max_size];
int head = 0;
int tail = 0;
int main()
{
    int n, m;
    std::cin >> n >> m;
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        int p, c;
        std::cin >> p >> c;
        queue[____(1)____] = p;
        while ( ____(2)____ ) {
            if ( ____(3)____ ) {
                queue[head] -= c;
                sum += c;
                c = 0;
            }
            else {
                int amount = ____(4)____;
                c -= amount;
                sum += amount;
            }
        }
        if ( ____(5)____ > m) {
            head++;
        }
    }
    std::cout << sum << "\n";
}
  1. (1) 处应填( )。

{{ select(36) }}

  • tail
  • tail+1
  • ++tail
  • tail++
  1. (2) 处应填( )。

{{ select(37) }}

  • head < tail || c > 0
  • head <= tail || c > 0
  • head < tail and c > 0
  • head <= tail and c > 0
  1. (3) 处应填( )。

{{ select(38) }}

  • queue[head] > c
  • queue[tail] > c
  • queue[head + 1] > c
  • queue[tail - 1] > c
  1. (4) 处应填( )。

{{ select(39) }}

  • queue[head++]
  • queue[++head]
  • queue[tail--]
  • queue[--tail]
  1. (5) 处应填( )。

{{ select(40) }}

  • head - tail
  • tail - head
  • tail - head - 1
  • tail - head + 1

第2题

给定一个 11nn 的排列 p1,p2,,pnp_1,p_2,\ldots,p_n,请统计排列中所有长度大于等于 22 的连续子序列的次大数之和。

定义 max2(ai,ai+1,,aj)\max_2(a_i,a_{i+1},\ldots,a_j) 表示从 aia_i 开始到 aja_j 结束的连续子序列中,排名第二大的数,这个数就是一个连续子序列的次大数之和。

题目就是要求:

$$\sum_{1 \le i < j \le n} \max_2(a_i,a_{i+1},\ldots,a_j)$$

solve 用于解决这个问题。

int q[maxn];
int prev[maxn];
int next[maxn];
long long solve(int n, int p[])
{
    for (int i = 1; i <= n; ++i)
    {
        ____(1)____ ;
    }
    p[0] = q[0] = prev[0] = 0;
    p[n+1] = q[n+1] = next[n+1] = n+1;
    for (int i = 1; i <= n; ++i)
    {
        int num = ____(2)____;
        int prev_num = p[i-1];
        int next_num = p[i+1];
        prev[num] = ____(3)____;
        next[num] = ____(4)____;
    }
    long long sum = 0;
    for (int num = 1; num <= n; ++num) {
        int prev_num = prev[num];
        int prev_prev_num = prev[prev_num];

        int next_num = next[num];
        int next_next_num = next[next_num];

        sum += (long long) num * ____(5)____ * (q[next_num] - q[num]);
        sum += (long long) num * (q[num] - q[prev_num]) * ____(6)____ ;

        ____(7)____ = prev_num;
        ____(8)____ = next_num;
    }
    return sum;
}
  1. (1) 处应填( )。

{{ select(41) }}

  • q[p[i]] = i
  • q[i] = p[i]
  • q[i] = 1
  • q[i] = i
  1. (2) (3) (4) 处应填( )。

{{ select(42) }}

  • p[i]prev_numnext_num
  • q[i]next_numprev_num
  • p[i]prev_numnext_num
  • q[i]next_numprev_num
  1. (5) 处应填( )。

{{ select(43) }}

  • (q[prev_num] - q[prev_prev_num])
  • (q[next_next_num] - q[prev_num])
  • (q[next_num] - q[prev_prev_num])
  • (q[next_next_num] - q[next_num])
  1. (6) 处应填( )。

{{ select(44) }}

  • (q[prev_num] - q[prev_prev_num])
  • (q[next_next_num] - q[prev_num])
  • (q[next_num] - q[prev_prev_num])
  • (q[next_next_num] - q[next_num])
  1. (7) (8) 处应填( )。

{{ select(45) }}

  • prev[prev_num]next[next_num]
  • prev[next_num]next[prev_num]
  • next[prev_num]prev[next_num]
  • next[next_num]prev[prev_num]