1. 程式人生 > >noip提高組初賽有感——

noip提高組初賽有感——

本人第一次考試,感覺還好吧,誤打誤撞報了個提高組,覺得還是有點虧了(把普及組的臉甩在地上狠狠摩擦那種)。。蒟蒻的我答後面的題時就開始困難了,但多選題答得還可以。考場有提前交卷的,大神總是很多呀… 不過第二大題第一問真的很厲害…表示很慌

第二十四屆全國青少年資訊學奧林匹克聯賽初賽 提高組 C++語言試題

競賽時間:2018 年 10 月 13 日 14:30~16:30

選手 注意:  試題紙共有 10 頁,答題紙共有 2 頁,滿分 100 分。請在答題紙上作答,寫 在試題紙上的一律無效。  不得使用任何電子裝置(如計算器、手機、電子詞典等)或查閱任何書籍資 料。

一、單項選擇題(共 10 題,每題 2 分,共計 20 分;每題有且僅有一個正確選項)

  1. 下列四個不同進位制的數中,與其它三項數值上不相等的是( )。

A. (269)16 B. (617)10 C. (1151)8 D. (1001101011)2

  1. 下列屬於解釋執行的程式設計語言是( )。 A. C B. C++ C. Pascal D. Python

  2. 中國計算機學會於( )年創辦全國青少年計算機程式設計競賽。 A. 1983 B. 1984 C. 1985 D. 1986

  3. 設根節點深度為 0,一棵深度為 h 的滿 k(k>1)叉樹,即除最後一層無任何子節點外,每一層上的所有結點都有 k 個子結點的樹,共有( )個結點。 A. (k h+1 - 1) / (k - 1) B. k h-1 C. k h D. (k h-1) / (k - 1)

  4. 設某演算法的時間複雜度函式的遞推方程是 T(n) = T(n - 1) + n(n 為正整數)及 T(0) = 1,則該演算法的時間複雜度為( )。 A. O(log n) B. O(n log n) C. O(n) D. O(n2)

  5. 表示式 a * d - b * c 的字首形式是( )。 A. a d * b c * - B. - * a d * b c C. a * d - b * c D. - * * a d b c

  6. 在一條長度為 1 的線段上隨機取兩個點,則以這兩個點為端點的線段的期望 長度是( )。 A. 1 / 2 B. 1 / 3 C. 2 / 3 D. 3 / 5

  7. 關於 Catalan 數 Cn = (2n)! / (n + 1)! / n!,下列說法中錯誤的是( )。 A. Cn 表示有 n + 1 個結點的不同形態的二叉樹的個數。 B. Cn 表示含 n 對括號的合法括號序列的個數。 C. Cn 表示長度為 n 的入棧序列對應的合法出棧序列個數。 D. Cn 表示通過連線頂點而將 n + 2 邊的凸多邊形分成三角形的方法個數。

  8. 假設一臺抽獎機中有紅、藍兩色的球,任意時刻按下抽獎按鈕,都會等概率獲得紅球或藍球之一。有足夠多的人每人都用這臺抽獎機抽獎,假如他們的策略均為:抽中藍球則繼續抽球,抽中紅球則停止。最後每個人都把自己獲得的所有球放到一個大箱子裡,最終大箱子裡的紅球與藍球的比例接近於 ( )。 A. 1 : 2 B. 2 : 1 C. 1 : 3 D. 1 : 1

  9. 為了統計一個非負整數的二進位制形式中 1 的個數,程式碼如下: int CountBit(int x) { int ret = 0; while (x) { ret++; ________; } return ret; } 則空格內要填入的語句是( )。 A. x >>= 1 B. x &= x - 1 C. x |= x >> 1 D. x <<= 1

二 、不定項選擇題(共 5 題,每題 2 分,共計 10 分;每題有一個或多個正確選項,多選或少選均不得分 )

  1. NOIP 初賽中,選手可以帶入考場的有( )。 A. 筆 B. 橡皮 C. 手機(關機) D. 草稿紙

  2. 2-3 樹是一種特殊的樹,它滿足兩個條件: (1)每個內部結點有兩個或三個子結點; (2)所有的葉結點到根的路徑長度相同。 如果一棵 2-3 樹有 10 個葉結點,那麼它可能有( )個非葉結點。 A. 5 B. 6 C. 7 D. 8

  3. 下列關於最短路演算法的說法正確的有( )。 A. 當圖中不存在負權迴路但是存在負權邊時,Dijkstra 演算法不一定能求出源點到所有點的最短路。 B. 當圖中不存在負權邊時,呼叫多次 Dijkstra 演算法能求出每對頂點間最短路徑。 C. 圖中存在負權迴路時,呼叫一次 Dijkstra 演算法也一定能求出源點到所有點的最短路。 D. 當圖中不存在負權邊時,呼叫一次 Dijkstra 演算法不能用於每對頂點間最短路計算。

  4. 下列說法中,是樹的性質的有( )。 A. 無環 B. 任意兩個結點之間有且只有一條簡單路徑 C. 有且只有一個簡單環 D. 邊的數目恰是頂點數目減 1

  5. 下列關於圖靈獎的說法中,正確的有( )。 A. 圖靈獎是由電氣和電子工程師協會(IEEE)設立的。 B. 目前獲得該獎項的華人學者只有姚期智教授一人。 C. 其名稱取自電腦科學的先驅、英國科學家艾倫•麥席森•圖靈。 D. 它是計算機界最負盛名、最崇高的一個獎項,有“計算機界的諾貝爾獎” 之稱。

三、 問題求解(共 2 題,每題 5 分,共計 10 分)

  1. 甲乙丙丁四人在考慮週末要不要外出郊遊。 已知①如果週末下雨,並且乙不去,則甲一定不去;②如果乙去,則丁一定 去;③如果丙去,則丁一定不去;④如果丁不去,而且甲不去,則丙一定不 去。如果週末丙去了,則甲________(去了/沒去)(1分),乙________(去 了/沒去)(1分),丁________(去了/沒去)(1分),週末________(下雨/ 沒下雨)(2分)。

  2. 方程 a*b = (a or b) * (a and b),在 a,b 都取 [0, 31] 中的整數時, 共有_____組解。(*表示乘法;or表示按位或運算;and表示按位與運算)

四、閱讀程式寫結果(共 4 題,每題 8 分,共計 32 分)

  1. #include int main() { int x; scanf("%d", &x); int res = 0; for (int i = 0; i < x; ++i) { if (i * i % x == 1) { ++res; } } printf("%d", res); return 0; }

輸入:15 輸出:_________

  1. #include int n, d[100]; bool v[100]; int main() { scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", d + i); v[i] = false; } int cnt = 0; for (int i = 0; i < n; ++i) { if (!v[i]) { for (int j = i; !v[j]; j = d[j]) { v[j] = true; } ++cnt; } } printf("%d\n", cnt); return 0; }

輸入:10 7 1 4 3 2 5 9 8 0 6 輸出:_________

  1. #include using namespace std; string s; long long magic(int l, int r) { long long ans = 0; for (int i = l; i <= r; ++i) { ans = ans * 4 + s[i] - ‘a’ + 1; } return ans; } int main() { cin >> s; int len = s.length(); int ans = 0; for (int l1 = 0; l1 < len; ++l1) { for (int r1 = l1; r1 < len; ++r1) { bool bo = true; for (int l2 = 0; l2 < len; ++l2) { for (int r2 = l2; r2 < len; ++r2) { if (magic(l1, r1) == magic(l2, r2) && (l1 != l2 || r1 != r2)) { bo = false; } } } if (bo) { ans += 1; } } } cout << ans << endl; return 0; }

輸入:abacaba 輸出:_________

  1. #include using namespace std; const int N = 110; bool isUse[N]; int n, t; int a[N], b[N]; bool isSmall() { for (int i = 1; i <= n; ++i) if (a[i] != b[i]) return a[i] < b[i]; return false; } bool getPermutation(int pos) { if (pos > n) { return isSmall(); } for (int i = 1; i <= n; ++i) { if (!isUse[i]) { b[pos] = i; isUse[i] = true; if (getPermutation(pos + 1)) { return true; } isUse[i] = false; } } return false; } void getNext() { for (int i = 1; i <= n; ++i) { isUse[i] = false; } getPermutation(1); for (int i = 1; i <= n; ++i) { a[i] = b[i]; } } int main() { scanf("%d%d", &n, &t); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } for (int i = 1; i <= t; ++i) { getNext(); } for (int i = 1; i <= n; ++i) { printf("%d", a[i]); if (i == n) putchar(’\n’); else putchar(’ '); } return 0; } 輸入1:6 10 1 6 4 5 3 2 輸出1:_________(3分) 輸入2:6 200 1 5 3 4 2 6 輸出2:_________(5分)

五、完善程式(共 2 題,每題 14 分,共計 28 分)

  1. 對於一個1到?的排列?(即1到?中每一個數在?中出現了恰好一次),令??為第?個位置之後第一個比??值更大的位置,如果不存在這樣的位置,則?? = ? + 1。舉例來說,如果? = 5且?為1 5 4 2 3,則?為2 6 6 5 6。

下列程式讀入了排列?,使用雙向連結串列求解了答案。試補全程式。(第二空 2 分,其餘 3 分)資料範圍 1 ≤ ? ≤ 105。

#include using namespace std; const int N = 100010; int n; int L[N], R[N], a[N]; int main() { cin >> n; for (int i = 1; i <= n; ++i) { int x; cin >> x; (1) ; } for (int i = 1; i <= n; ++i) { R[i] = (2) ; L[i] = i - 1; } for (int i = 1; i <= n; ++i) { L[ (3) ] = L[a[i]]; R[L[a[i]]] = R[ (4) ]; } for (int i = 1; i <= n; ++i) { cout << (5) << " "; } cout << endl; return 0; }

  1. 一隻小豬要買 N 件物品(N 不超過 1000)。

它要買的所有物品在兩家商店裡都有賣。第 i 件物品在第一家商店的價格是 a[i],在第二家商店的價格是 b[i],兩個價格都不小於 0 且不超過 10000。如果在第一家商店買的物品的總額不少於 50000,那麼在第一家店買的物品都可以打 95 折(價格變為原來的 0.95 倍)。 求小豬買齊所有物品所需最少的總額。

輸入:第一行一個數 N。接下來 N 行,每行兩個數。第 i 行的兩個數分別代表 a[i],b[i]。輸出:輸出一行一個數,表示最少需要的總額,保留兩位小數。 試補全程式。(第一空 2 分,其餘 3 分)

#include #include using namespace std; const int Inf = 1000000000; const int threshold = 50000; const int maxn = 1000; int n, a[maxn], b[maxn]; bool put_a[maxn]; int total_a, total_b; double ans; int f[threshold]; int main() { scanf("%d", &n); total_a = total_b = 0; for (int i = 0; i < n; ++i) { scanf("%d%d", a + i, b + i); if (a[i] <= b[i]) total_a += a[i]; else total_b += b[i]; } ans = total_a + total_b; total_a = total_b = 0; for (int i = 0; i < n; ++i) { if ( (1) ) { put_a[i] = true; total_a += a[i]; } else { put_a[i] = false; total_b += b[i]; } } if ( (2) ) { printf("%.2f", total_a * 0.95 + total_b); return 0; } f[0] = 0; for (int i = 1; i < threshold; ++i) f[i] = Inf; int total_b_prefix = 0; for (int i = 0; i < n; ++i) if (!put_a[i]) { total_b_prefix += b[i]; for (int j = threshold - 1; j >= 0; --j) { if ( (3) >= threshold && f[j] != Inf) ans = min(ans, (total_a + j + a[i]) * 0.95 + (4) ); f[j] = min(f[j] + b[i], j >= a[i] ? (5) : Inf); } } printf("%.2f", ans); return 0; }

第二十四屆全國青少年資訊學奧林匹克聯賽初賽提高組參考答案一、單項選擇題(共 10 題,每題2 分,共計20 分) 1 2 3 4 5 6 7 8 9 10 D D B A D B B A D B 二、 不定項選擇題(共 5 題,每題 2 分,共計 10 分;每題有一個或多個正確選項,沒有部分分) 1 2 3 4 5 AB CD ABD ABD BCD 三、 問題求解(共 2 題,每題 5 分,共計10 分)

  1. 去了 沒去 沒去 沒下雨 (第4 空 2 分,其餘 1 分)
  2. 454 四、閱讀程式寫結果(共 4 題,每題 8 分,共計 32 分)
  3. 4
  4. 6
  5. 16
  6. 輸出1:2 1 3 5 6 4 (3分) 輸出2:3 2 5 6 1 4 (5分) 五、完善程式(共計 28 分,以下各程式填空可能還有一些等價的寫法,由各省賽區組織本省專家審定及上機驗證,可以不上報 CCF NOI 科學委員會複核)

1 . (1) a[x] := i a[x] = i 3 (2) i + 1 2 (3) R[a[i]] 3 (4) a[i] 3 (5) R[i] 3 2 . (1) a[i] * 0.95 <= b[i] 或 b[i] >= a[i] * 0.95 2 (2) total_a >= threshold 或 threshold <= total_a 或 total_a >= 50000 或 50000 <= total_a 3 (3) total_a + j + a[i] 3 (4) f[j] + total_b - total_b_prefix 3 (5) f[j - a[i]] 3