日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2019 CSP-J 真题 题目、答案以及解析

發布時間:2023/12/8 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019 CSP-J 真题 题目、答案以及解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 寫在前面的話
  • 題目
  • 解析
    • 單項選擇題
      • 1.
      • 2.
      • 3.
      • 4.
      • 5.
      • 6.
      • 7.
      • 8.
      • 9.
      • 10.
      • 11.
      • 12.
      • 13.
      • 14.
      • 15.
    • 閱讀程序題
      • 一、
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      • 二、
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      • 三、
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
    • 完善程序題
      • 一、
        • 1
        • 2
        • 3
        • 4
        • 5
      • 二、
        • 1
        • 2
        • 3
        • 4 //部分思路(我到現在也沒搞懂)懂了的跟我說一聲啊!!!
        • 5
  • 尾聲

寫在前面的話

最近快要CSP了,為了幫助大家[zì jǐ]更好的復習歷年真題特地作此題解一篇。
我寫完之后看了一遍,感覺有點啰嗦,大家看不看隨意。
還有,有沒有大佬講講閱讀程序最后一題的倒數第二問?
蒟蒻我看不懂😭😭😭😭😭😭😭😭😭😭

題目

洛谷版
CCF版

建議使用CCF版。因為洛谷版有打印錯誤。
兩種版本題目都有題目、答案所以這里不過多講解,下面是解析內容↓

解析

單項選擇題

1.

這題沒什么可講的,死知識,自己背就完了

2.

與運算即數位對齊,若兩個數相同數位都為True,運算結果即為True, 否則為False
我們來將兩數執行上述操作:

1 1 1 0 1 1 1 0 0 1 0 1 1 1
0 1 0 1 1 0 1 1 1 0 1 0 1 1
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
0 1 0 0 1 0 1 0 0 0 0 0 1 1

答案就出來了。

3.

32位即為32個二進制位,一個字節8個二進制位,32 / 8 = 4
于是乎答案出來了。

4.

b從1~C,共循環了C次,減去C個1即為-C
于是乎,答案出來了

5.

折半查找的復雜度為O(long n),log 100 為6~7之間,最大值即為7

6.

鏈表數據結構的特點為:

  • 執行插入、刪除等操作消耗O(1)的時間復雜度;
  • 訪問元素需要消耗O(n)的復雜度;
  • 不必事先預估所需空間;
  • 不可隨機訪問元素。
  • 所消耗的空間與普通數組成正比例

所以,答案大家可以看出來了吧

7.

這題沒什么好說的,直接人肉暴力一下就好了。

注意!袋子和袋子沒有區別,球和球也沒有區別,所以:

  • 8 0 0 0 0
  • 0 8 0 0 0

沒有區別

有如下結果:

  • 8 0 0 0 0
  • 7 1 0 0 0
  • 6 2 0 0 0
  • 6 1 1 0 0
  • 5 3 0 0 0
  • 5 2 1 0 0
  • 5 1 1 1 0
  • 4 4 0 0 0
  • 4 3 1 0 0
  • 4 2 2 0 0
  • 4 2 1 1 0
  • 4 1 1 1 1
  • 3 3 2 0 0
  • 3 3 1 1 0
  • 3 2 2 1 0
  • 3 2 1 1 1
  • 2 2 2 2 0
  • 2 2 2 1 1
  • 一共18個答案。

    8.

    用一維數組儲存二叉樹的方法題目中也說了:

    (根結點的下標為1,若某結點的下標為i ,則其左孩子位于下標2i處、右孩子位于下標2i+l處)

    那么,問題來了:如果某非葉子節點沒有左孩子,那么這一個下標放什么呢?

    空著。

    因為如果把其他節點放過來了,就無法滿足上述條件了,那么就無法正確訪問該二叉樹了。

    所以,我們要將其余位置補全,使其變成一棵完全二叉樹

    原圖如下:

    更改為完全二叉樹后如下:


    可知共需15個節點的空間
    (圖畫的有點抽象,請諒解)

    9.

    這個你要是不會,請到小學回爐重造

    10.

    將兩數分別分解質因數即可。

    11.

    類似于背包問題
    數據范圍較小,人肉DP即可

    12.

    重復最少 即抽取結果各個花色盡可能平均,若每種花色各抽4張,一共12張,還需再抽一張,故最少5張花色相同。

    13.

    可顛倒的五位數:

    • 第一位有5種情況(0、1、6、8、9)
    • 第二位有5種情況(0、1、6、8、9)
    • 第三位有3種情況(6、9不行,因為顛倒后與原來不符,而中間位顛倒后依然在原來的地方)
    • 第四、第五位只有1種情況(必須與第一、第二位對應)

    根據乘法原理,共5x5x3 = 75種情況。

    愿意的可以人肉暴力一下。

    14.

    這是一道二叉樹的遍歷題。后中推前。
    可以通過后序遍歷 + 中序遍歷還原二叉樹。
    還原過程如下:

    后序遍歷:D G J H E B I F C A

    中序遍歷:D B G E H J A C I F

  • 根據后序遍歷確定根節點為A
  • 根據中序遍歷確定左子樹為D B G E H J,右子樹為C I F
  • 根據后序遍歷分別確定兩個子樹的根節點
  • 根據中序遍歷確定兩個子樹的左右子樹
  • 以此類推
  • 最終,可以還原二叉樹。
    然后進行前序遍歷即可。

    P.S.P.S.P.S. 如果連前中后序遍歷都不知道的同學,請自行學習相關知識。

    15.

    死知識:“計算機領域的諾貝爾獎”為“圖靈獎”

    閱讀程序題

    一、

    #include <cstdio> #include <cstring> using namespace std; char st[100]; int main() {scanf("%s", st);int n = strlen(st);for (int i = 1; i <= n; ++i) {if (n % i == 0) {char c = st[i - 1];if (c >= 'a')st[i - 1] = c - 'a' + 'A';}}printf("%s", st);return 0; }

    1


    輸入字符串可以由任意字符組成,只不過本代碼僅僅處理小寫字母而已。

    2


    若進行上述更改,第九行 則會發生÷0問題,RE

    3

    很明顯錯誤。
    舉個反例:aaaaaaaa
    原程序運行結果:AAaAaaaA
    修改后運行結果:AAaaaaaa

    大家可以自行復制代碼嘗試一下。

    4

    正確
    簡單看一看代碼就會發現:特定字符的ASCLL碼≥97時,才會進行修改,而大寫字母Z的ASCLL碼也才71。
    所以不會進行任何更改

    5

    至多

    符合情況的都要算。
    有兩層篩選條件:
    第九行:n % i == 0
    第十一行:c >= 'a'
    只要輸入的都是小寫字母,就可以滿足第十一行的條件。
    而第九行的條件可理解為:“是n的因數”

    若輸入的字符串長度為18

    即:n = 18
    18的因數共有6個:1、2、3、6、9、18

    可知答案。

    6

    本題是上一題的變體,相信看懂了上一題的同學一定可以明白:本題問的是“?有36個因數”
    這里教大家一個快速求因數個數的方法:
    先將其分解因數
    然后將所有質因數的指數+1,在相乘。

    我們來逐一分解:

    36 = 22 * 32
    (2+1)(2+1) = 9

    100000 = 2? * 5?
    (5+1)(5+1) = 36

    答案就出來了。
    有興趣的同學可以證明一下我提供的方法。

    二、

    #include<cstdio> using namespace std; int n, m; int a[100], b[100];int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i)a[i] = b[i] = 0;for (int i = 1; i <= m; ++i) {int x, y;scanf("%d%d", &x, &y);if (a[x] < y && b[y] < x) {if (a[x] > 0)b[a[x]] = 0;if (b[y] > 0)a[b[y]] = 0;a[x] = y;b[y] = x;}}int ans = 0;for (int i = 1; i <= n; ++i) {if (a[i] == 0)++ans;if (b[i] == 0)++ans;}printf("%d", ans);return 0; }

    1

    錯誤
    可以嘗試證明一下:
    第一次運行一定會進入第13行的if語句,則一定會有兩個數被身為非零的數。

    • 之后如果沒有進入if語句,則這兩個數一直非零,直到運行結束,ans = n - 2
    • 如果進入了,則會將兩個數設為0,兩個數設為非0,此時最好情況下0的個數也不會改變

    綜上所述:ans最大為n-2

    2

    錯誤
    舉個反例:

    3 1
    1 2

    在執行完第十行的循環之后,數組如下:

    下標:123
    數組a:200
    數組b:010

    在第一次執行完27行的ans++時,ans == 1

    3


    舉個反例:

    1 1
    1 1

    很明顯了吧?

    4

    依然錯
    舉個反例:
    2 1
    1 2
    大家自己算一算

    5

    自己造一組數據即可:
    例如:

    3 3
    1 1
    2 2
    3 3

    ans:0

    有興趣的同學可以自行證明,愿意的話發給我看看

    6

    同樣,自己造數據

    3 3
    1 1
    2 1
    3 1

    ans:4

    三、

    #include <iostream> using namespace std; const int maxn = 10000; int n; int a[maxn]; int b[maxn]; int f(int l, int r, int depth) {if (l > r)return 0;int min = maxn, mink;for (int i = l; i <= r; ++i) {if (min > a[i]) {min = a[i];mink = i;}}int lres = f(l, mink - 1, depth + 1);int rres = f(mink + 1, r, depth + 1);return lres + rres + depth * b[mink]; } int main() {cin >> n;for (int i = 0; i < n; ++i)cin >> a[i];for (int i = 0; i < n; ++i)cin >> b[i];cout << f(0, n - 1, 1) << endl;return 0; }

    1

    錯誤
    相等的數字對該程序沒有任何影響

    這題選錯的講講你的思路唄😁😁😁

    2

    正確
    返回值有兩種情況:

    • return 0
    • return lres + rres + depth * b[mink];

    第一種情況不受b數組的影響,不用考慮
    第二種情況受四個因素的影響:左孩子、右孩子、數組b、depth
    由于數組b全部為零,第二種情況只受左右孩子的影響。

    左右孩子又有兩種情況了:葉子節點、非葉子節點
    前一個繼續往下遞歸,后一個return 0

    所以,發現了嗎?返回值要么是0, 要么是0+0+0

    所以, ans = ……

    3

    這題的代碼是一道遞歸題,它的 最好/最壞 情況類似于快速排序
    所以,最壞情況為每次將最左邊/右邊的一個端點去掉,一共需要去掉n次而每一層遞歸都會比較n次
    總復雜度約為O(n2),n = 100時,約為10000次,最接近的即為A

    4

    最好情況下,每次都能二分整個區間,復雜度為O(n log n),n = 100時,在600到700之間,故選D

    5

    要想輸出最大,遞歸的深度也要最大,每次都去掉左端點(權值最小)
    這樣,ans將會達到12 + 22 + 32 + … + n2,n = 10時,答案為385。

    6

    Tips:Tips:Tips 使用“洛谷有題”的同學注意了,題目打錯了,原題應當為:

    當 n=100 時,若 b 數組滿足,對于任意 0 ≤ i < n,都有 b[i] = 1,那么輸出最小為( )

    要想結果最小,就要讓二叉樹盡可能平衡,最平衡的二叉樹即為完全二叉樹
    用100個節點搭建一棵完全二叉樹,每層的節點數依次為:1,2,4,8,16,32,37
    將每層的節點數與其對應的權值相乘,求出總和即可。

    (有沒有人像我一樣 把最后一層的節點數算成64,然后抓耳撓腮想不明白?有的話在評論區里打一個心有靈犀😁😁😁)

    完善程序題

    一、

    #include <cstdio> using namespace std; int n; const int max_size = 1 << 10;int res[max_size][max_size];void recursive(int x, int y, int n, int t) {if (n == 0) {res[x][y] =;return;}int step = 1 << (n - 1);recursive(, n - 1, t);recursive(x, y + step, n - 1, t);recursive(x + step, y, n - 1, t);recursive(, n - 1, !t); }int main() {scanf("%d", &n);recursive(0, 0,);int size =;for (int i = 0; i < size; i++) {for (int j = 0; j < size; j++)printf("%d", res[i][j]);puts("");}return 0; }

    1

    t表示這一個格子應當寫什么
    就算你想不明白這一點,換個角度想:要是這里不用t,t有什么用?

    2

    根據一開始的例子,可知:每一次變換之后,右下格變為與自己不同的一項,右、下、自己變為自己原本的數字。

    而這一行t沒有變,所以是右、下、自己中的一個。
    而右、下已經寫過了,所以x、y不用變

    3

    用CCF提供的題庫的同學注意了!
    該題的解析似乎有錯:

    當然,也有可能是我錯了,歡迎指出

    下面是我的思路:
    這里t做了變化,所以是右下角,即兩個都+step

    4

    初始位置應該為0(見題目),深度應該為n(初始狀態為遞歸0次)

    5

    矩陣最終大小應當為2n,即 1 << n

    二、

    本題與計數排序有著密切的關系,不會的同學可以先學習一下相關知識

    #include <cstdio> #include <cstring> using namespace std; const int maxn = 10000000; const int maxs = 10000;int n; unsigned a[maxn], b[maxn],res[maxn], ord[maxn]; unsigned cnt[maxs + 1]; int main() {scanf("%d", &n);for (int i = 0; i < n; ++i) scanf("%d%d", &a[i], &b[i]);memset(cnt, 0, sizeof(cnt));for (int i = 0; i < maxs; ++i); // 利用 cnt 數組統計數量for (int i = 0; i < n; ++i) cnt[i + 1] += cnt[i];for (int i = 0; i < n; ++i); // 記錄初步排序結果memset(cnt, 0, sizeof(cnt));for (int i = 0; i < n; ++i); // 利用 cnt 數組統計數量for (int i = 0; i < maxs; ++i)cnt[i + 1] += cnt[i];for (int i = n - 1; i >= 0; --i)// 記錄最終排序結果for (int i = 0; i < n; i++)printf("%d %d",);return 0; }

    1

    有了注釋應該很容易理解,這里在對第二個參數進行計數排序(一下稱之為初排)

    2

    ord[i]表示:在輸入時下標為i的數字 在對第二個關鍵字排序之后的下標
    知道了這個應該很好選

    3

    對第一個關鍵字進行計數排序(以下稱之為復排)

    4 //部分思路(我到現在也沒搞懂)懂了的跟我說一聲啊!!!

    答案為 res[--cnt[a[ord[i]]]] = ord[i]
    我們來理一理思路(一層層數組看的我頭暈)

    首先,i表示輸入時的第i個數
    ord[i] 表示 第i個數現在(初排后)的位置
    a[ord[i]] 表示 i初排后的位置上 初排前的元素 的第一個關鍵字
    --cnt[a[ord[i]]] 表示 i初排后的位置上 初排前的元素 的第一個關鍵字 復排后應該在的位置
    res[--cnt[a[ord[i]]]] 表示 復排后 i初排后的位置上 初排前的元素 的第一個關鍵字 復排后應該在的位置的下標
    res[--cnt[a[ord[i]]]] = ord[i] 表示……
    將 復排后 i初排后的位置上 初排前的元素 的第一個關鍵字 復排后應該在的位置的下標 設為 初排后 i 的位置

    然后……
    我就懵了

    懇請大佬幫忙!!!

    5

    res存儲的就是最終結果了

    尾聲

    這篇文章對你的幫助大嗎?
    謝謝閱讀。
    有什么改進建議歡迎評論區講。

    總結

    以上是生活随笔為你收集整理的2019 CSP-J 真题 题目、答案以及解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。