第十二屆藍橋杯大賽軟件賽省賽第二場 C/C++ 大學 A 組 題解


A. 雙階乘

輸出 \(2021!! \bmod 10^4\)

for 循環每次減 \(2\) 即可


B. 格點

求第一象限整點中,\(xy\leq 2021\) 的整點個數

for 循環暴力遍歷 \(2021\times 2021\) 的平面,統計答案即可


C. 整數分解

\(2021\) 分解為 \(5\) 個正整數的有序分解方案數

\(f_{n, p}\) 表示 \(n\) 被分解為 \(p\) 個正整數的有序分解方案數

搜索或遞推均可


D. 城邦

給定編號為 \(1\)~\(2021\)\(2021\) 元完全圖,定義點權為編號數碼的集合的元素和(例如 : \(2021\) 的為 \(2+0+1=3\))。
定義連接兩點 \(a, b\) 的邊權為兩點點權之和
求 MST 邊權和

先暴力把 \(1\)~\(2021\) 的點權跑出來,然后所有邊已知

由於是提交答案題,跑 Kruskal 或者 Prim 算法均可


E. 游戲

給定數值 \(n\) ,兩人輪流進行游戲。每一輪可將數字 \(n\) 化為其因數之一,直到 \(n\) 變為 \(1\)
\(n=20210509\) 時的游戲方案數

\(f_d\) 表示從 \(d\) 開始,游戲的方案數,初始 \(f_1=1\)

用刷表法,將 \(d\) 的所有倍數 \(n\) ,均執行 \(f_n+=f_d\)

復雜度為 \(\displaystyle \sum_{i=1}^n \lfloor{n\over i}\rfloor\approx \sum_{i=1}^n {n\over i}=O(n\log n)\)

期望時長為 \(5s\)


F. 小平方

\([1,n)\cap Z\) 中,模 \(n\) 意義下,平方嚴格小於 \({n\over 2}\) 的數的個數
\(n\leq 10^4\)

for 循環暴力驗證即可


G. 完全平方數

給定正整數 \(n\) ,求最小的正整數 \(x\) ,使得 \(nx\) 為完全平方數
\(n\leq 10^{12}\)

考慮到 \(n\) 大於 \(\sqrt n\) 的質因數最多 \(1\)

否則任意兩個乘起來也超過 \(n\)

因此優先用歐拉篩或埃氏篩打出 \(\sqrt n\leq 10^6\) 范圍內的質因數,將該部分的每個質數在 \(n\) 中的次數求出

若次數為奇數,則 \(x\) 中必須出現奇數次該質數,故取 \(1\) 次;否則 \(x\) 中需為偶數次,取 \(0\)

最后驗證 \(n\) 是否仍有其他質因數,若有,則 \(x\) 中該質因數必須出現奇數次,同樣取 \(1\)


H. 負載均衡

\(n\) 台計算機,第 \(i\) 台算力為 \(v_i\)
\(m\) 個任務,每個在 \(a_i\) 時刻送達,需要消耗 \(b_i\) 號計算機 \(c_i\) 的時間與 \(d_i\) 的算力
若分配任務時,計算機算力充足,必須執行任務,並輸出剩余算力;否則輸出 \(-1\)
\(n, m\leq 2\times 10^5\)

考慮將任務拆成兩瓣:

  1. \(a_i\) 時到達的,消耗 \(b_i\) 號計算機 \(d_i\) 算力的
  2. \(a_i+c_i\) 時到達的,消耗 \(b_i\) 號計算機 \(-d_i\) 算力的

且第二個子任務奏效當且僅當第一個子任務奏效

因此,對任務標記原來的序號 \(i\) ,再按時間排序;時間相同時,算力為負數的任務(第二類任務)優先

維護每台計算機的剩余算力,按時間順序執行任務

當執行第一類任務時,檢查算力是否充足,充足則執行當前任務,更新剩余算力並輸出;若不充足,則標記當前任務原來序號 \(i\) 不生效,並且輸出 \(-1\)

當執行第二類任務時,檢查當前任務是否生效,若不生效則直接退出;否則更新算力

復雜度為 \(O(n\log n)\)


I. 國際象棋

規定國際象棋棋盤中,位於點 \((x,y)\) 的馬可以攻擊 \(8\) 個方向:

  1. \((x-2, y-1)\)
  2. \((x-2, y+1)\)
  3. \((x-1, y-2)\)
  4. \((x-1, y+2)\)
  5. \((x+1, y-2)\)
  6. \((x+1, y+2)\)
  7. \((x+2, y-1)\)
  8. \((x+2, y+1)\)
    \(n\times m\) 的棋盤中,放置 \(k\) 匹馬且不互相攻擊的方案數
    \(n\leq 6, m\leq 100, k\leq 20\)

狀壓 dp :預處理 \(n_{1, S}\) 表示當前行狀態狀態為 \(S\) 時,下一行的最大可選集合;\(n_{2, S}\) 表示下兩行最大可選集合;\(cnt_S\) 表示 \(|S|\)

\(f_{m, S, T, k}\) 表示第 \(m\) 行狀態為 \(S\) 且第 \((m-1)\) 行狀態為 \(T\) 時,放置了 \(k\) 匹馬且不互相攻擊的方案數

不難得出,當且僅當 \(S\subseteq n_{1, T}\) 時方程有意義,且初始狀態為 \(f_{1, S, 0, cnt_S}=1\)

狀態轉移采用刷表實現:將 \(f_{m, S, T, k}\) 刷到 \(\forall R\subseteq (n_{1, S}\cap n_{2, T}),f_{m+1, R, S, k+|R|}\)

答案為 \(\displaystyle \sum_S\sum_T f_{m, S, T, k}\)

發現第一維可以滾動成 \(m\bmod 2\) 形式,故空間復雜度為 \(2\times 2^n\times 2^n\times k=O(k\cdot 4^n)\)

時間復雜度為 \(m\times 2^n\times 2^n\times k+2^n\times 2^n=O(mk\cdot 4^n)\) ,顯然充足

甚至加上了 \(S\subseteq n_{1, T}\) 的限制,根本拉不到那么大


J. 完美序列

這題題目是真的繞

定義完美序列為:滿足除第 \(1\) 個數外,所有數為前一個數的因數的序列。
定義序列的完美值為:該序列所有完美子序列的長度最大值
\(1\)~\(n\) 的所有排列 \(P\) 中,每個排列中,所有長度為 \(\{n, (n-1), (n-2), \cdots , 1\}\) 的完美值的完美序列,它們的元素和
\(T\leq 10^5\) 組獨立詢問,每次詢問 \(n\leq 10^6\)

\(n=3\) 時,\(\{3, 2, 1\}\) 的完美值為 \(\{2, 1\}\) 的長度 \(2\)
考慮 \(n=3\) 的所有排列:

  1. \(\{1,2,3\}\) 不含長度為 \(2\) 的完美序列
  2. \(\{1,3,2\}\) 不含長度為 \(2\) 的完美序列
  3. \(\{2,1,3\}\) 含長度為 \(2\) 的完美序列 \(\{2, 1\}\),元素和為 \(3\)
  4. \(\{2,3,1\}\) 含長度為 \(2\) 的完美序列 \(\{2, 1\}, \{3, 1\}\),元素和為 \(7\)
  5. \(\{3,1,2\}\) 含長度為 \(2\) 的完美序列 \(\{3, 1\}\),元素和為 \(4\)
  6. \(\{3,2,1\}\) 含長度為 \(2\) 的完美序列 \(\{2, 1\}, \{3, 1\}\),元素和為 \(7\)
    故答案為 \(0+0+3+7+4+7=21\)

先考慮打出 \(f_n\) 表示嚴格以 \(n\) 開頭的完美子序列長度最大值,則有 \(\displaystyle f_n=\max_{d\mid n}f_d+1\)

因此,同上某題也是因數的,用刷表法算出 \(f_n\)

接着,根據定義,\(\{n, (n-1), (n-2), \cdots , 1\}\) 並沒有限制開頭值,故其完美值為 \(\displaystyle g_n=\max_{i=1}^n f_i\) ,動態刷前綴最大值更新即可

現考慮貢獻:設存在某個完美序列 \(v_{1, 2, 3, \cdots, g_n}\)

則元素和為 \(\displaystyle \sum_{i=1}^{g_n} v_i\),在所有排列中出現的方案數為 \(\displaystyle P(n, n-g_n)={n!\over g_n!}\),故貢獻為 \(\displaystyle (\sum_{i=1}^{g_n} v_i)\cdot {n!\over g_n!}\)

同時,對於另一個完美序列 \(w_{1, 2, 3, \cdots, g_n}\) ,貢獻同樣為 \(\displaystyle (\sum_{i=1}^{g_n} w_i)\cdot {n!\over g_n!}\) ,且和 \(v\) 的獨立

故需求出所有完美序列的所有元素和:\(A_n\) ,則答案為 \(A_n\cdot {n!\over g_n!}\)

現考慮如何求 \(A_n\)

先記 \(c_n\) 表示 \(n\) 開頭的完美序列個數

刷表求 \(f_n\) 時,考慮由 \(f_d\) 更新 \(f_n\) 的一幕

\(f_d+1=f_n\) 時,說明 \(n\) 的后續接 \(d\) 是當前最優的策略之一,故更新 \(\begin{cases}A_n+=A_d+n\times c_d\\c_n+=c_d\end{cases}\)

\(f_d+1>f_n\) 時,說明 \(n\) 的后續接 \(d\) 比之前的都更優,故更新 \(f_n=f_d+1\) ,且 \(\begin{cases}A_n=A_d+n\\c_n=c_d\end{cases}\)

同理,后續刷表求 \(g_n\) 時,由於 \(g_n=\max(g_{n-1}, f_n)\)

\(g_{n-1}=f_n\) 時,說明以 \(n\) 開始和以某些比 \(n\) 小的數開始都是最優策略,故更新 \(\begin{cases}A_n+=A_{n-1}\\c_n+=c_{n-1}\end{cases}\)

\(g_{n-1}>f_n\) 時,說明不以 \(n\) 開始是最優策略,故更新 \(\begin{cases}A_n=A_{n-1}\\c_n=c_{n-1}\end{cases}\)

算法瓶頸在打出 \(A_n\)\(g_n\) 以及階乘極其逆元,復雜度在於枚舉枚舉倍數的 \(O(n\log n)\) 和線性掃描的 \(O(n)\)

故總復雜度為 \(O(n\log n+T)\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM