第十二屆藍橋杯 2021年省賽真題 (C/C++ 大學B組)
- 這次的難度比上次大,主要表現在數據量大。
- 填空題的后兩道比較難。
A 空間(進制轉換)
本題總分:5 分(√)
問題描述
小藍准備用 256MB 的內存空間開一個數組,數組的每個元素都是 32 位二進制整數,如果不考慮程序占用的空間和維護內存需要的輔助空間,請問256MB 的空間可以存儲多少個 32 位二進制整數?
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
256 * 1024 * 1024* 8 / 32
答案67108864
B 卡片(模擬)
本題總分:5 分(√)
問題描述
小藍有很多數字卡片,每張卡片上都是數字 0 到 9。
小藍准備用這些卡片來拼一些數,他想從 1 開始拼出正整數,每拼一個,就保存起來,卡片就不能用來拼其它數了。
小藍想知道自己能從 1 拼到多少。
例如,當小藍有 30 張卡片,其中 0 到 9 各 3 張,則小藍可以拼出 1 到 10,但是拼 11 時卡片 1 已經只有一張了,不夠拼出 11。
現在小藍手里有 0 到 9 的卡片各 2021 張,共 20210 張,請問小藍可以從 1拼到多少?
提示:建議使用計算機編程解決問題。
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
思路
構造專門的判定函數check。
代碼
#include<cstdio>
#include<iostream>
using namespace std;
int s[10];
bool check(int x){
while(x){
int t=x%10;
x/=10;
if(--s[t]<0) return false; //不夠了
}
return true;
}
int main()
{
for(int i=0;i<10;i++){
s[i]=2021;
}
for(int i=1;;i++){
if(!check(i)) {
cout<<i-1<<endl;
return 0;
}
}
return 0;
}
C 直線(枚舉)
本題總分:10 分
問題描述
在平面直角坐標系中,兩點可以確定一條直線。如果有多點在一條直線上,那么這些點中任意兩點確定的直線是同一條。
給定平面上 2 × 3 個整點 { ( x , y ) ∣ 0 ≤ x < 2 , 0 ≤ y < 3 , x ∈ Z , y ∈ Z } ,即橫坐標是 0 到 1 (包含 0 和 1) 之間的整數、縱坐標是 0 到 2 (包含 0 和 2) 之間的整數的點。這些點一共確定了 11 條不同的直線。
給定平面上 20 × 21 20 × 2120×21 個整點 ( x , y ) ∣ 0 ≤ x < 20 , 0 ≤ y < 21 , x ∈ Z , 即橫坐標是 0 到 19 (包含 0 和 19 ) 之間的整數、縱坐標是 0 到 20 (包含 0 和 20) 之間的整數的點。請問這些點一共確定了多少條不同的直線。
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
思路
- 結構體Line。枚舉點對{k,b}。
- 判斷兩個double相等,保證他們的差在1e-8或者1e-6。
- 豎線是例外。
代碼
//直線(枚舉)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=200000;
struct Line{
double k,b;
bool operator <(const Line& t)const{
if(t.k!=k) return k<t.k;
else return b<t.b;
}
}l[maxn];
int n=0;
int main()
{
//枚舉點對
for(int x1=0;x1<20;x1++){
for(int y1=0;y1<21;y1++){
for(int x2=0;x2<20;x2++){
for(int y2=0;y2<21;y2++){
if(x1!=x2){
double k=(double)(y2-y1)/(x2-x1);
double b=y1-k*x1;
l[n++]={k,b}; //將點對存入結構體,n為此時點對的個數
}
}
}
}
}
//排序
sort(l,l+n);
//統計多少個不同的數對
int res=1;
for(int i=1;i<n;i++){
if(fabs(l[i].k-l[i-1].k)>1e-8||fabs(l[i].b-l[i-1].b)>1e-8){
res++;
}
}
cout<<res+20<<endl; //20條豎線
return 0;
}
答案
40257
D 貨物擺放(枚舉)
本題總分:10 分
問題描述
小藍有一個超大的倉庫,可以擺放很多貨物。現在,小藍有 n 箱貨物要擺放在倉庫,每箱貨物都是規則的正方體。小藍規定了長、寬、高三個互相垂直的方向,每箱貨物的邊都必須嚴格平行於長、寬、高。
小藍希望所有的貨物最終擺成一個大的立方體。即在長、寬、高的方向上分別堆 L 、 W 、 H L、W、H的貨物,滿足 n = L × W × H 。
給定 n nn,請問有多少種堆放貨物的方案滿足要求。
例如,當 n = 4 時,有以下 6 種方案:1 × 1 × 4 、 1 × 2 × 2 、 1 × 4 × 1 、 2 × 1 × 2 、 2 × 2 × 1 、 4 × 1 × 1 。
請問,當 n = 2021041820210418(注意有 16 位數字)時,總共有多少種方案?
提示:建議使用計算機編程解決問題。
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
思路
- n分解成三個數的方案數 n=abc,考慮順序。
- 先求n所有的約數。
- 本質就是約數的組合,暴力解可以了。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
typedef long long LL;
using namespace std;
//n分解成三個數的方案數 n=a*b*c,考慮順序
//先求n所有的約數
int main()
{
LL n;
cin>>n;
vector<LL> d;
for(LL i=1;i*i<=n;i++){
if(n%i==0){
d.push_back(i);
if(n/i!=i) d.push_back(n/i); //另一邊
}
}
int res=0;
for(auto a: d){
for(auto b: d){
for(auto c: d){
if(a*b*c==n){
res++;
}
}
}
}
cout<<res<<endl;
return 0;
}
答案
2430
注意
auto變量的使用博客鏈接
E 路徑
本題總分:15 分
問題描述
小藍學習了最短路徑之后特別高興,他定義了一個特別的圖,希望找到圖中的最短路徑。
小藍的圖由 2021 個結點組成,依次編號 1 至 2021 。
對於兩個不同的結點 a , b,如果 a 和 b 的差的絕對值大於 21 ,則兩個結點之間沒有邊相連;如果 a 和 b 的差的絕對值小於等於 21,則兩個點之間有一條長度為 a 和 b 的最小公倍數的無向邊相連。
例如:結點 1 和結點 23 之間沒有邊相連;結點 3 和結點 24 之間有一條無向邊,長度為 24 ;結點 15 和結點 25 之間有一條無向邊,長度為 75 。
請計算,結點 1 和結點 2021 之間的最短路徑長度是多少。
提示:建議使用計算機編程解決問題。
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
答案
10266837
算動規吧
F 時間顯示
時間限制: 1.0s 內存限制: 256.0MB 本題總分:15 分
在編譯時加入命令-std=c++11並✔
小藍要和朋友合作開發一個時間顯示的網站。在服務器上,朋友已經獲取了當前的時間,用一個整數表示,值為從 1970 年 1 月 1日 00:00:00 到當前時刻經過的毫秒數。
現在,小藍要在客戶端顯示出這個時間。小藍不用顯示出年月日,只需要顯示出時分秒即可,毫秒也不用顯示,直接舍去即可。
給定一個用整數表示的時間,請將這個時間對應的時分秒輸出。
輸入格式
輸入一行包含一個整數,表示時間。
輸出格式
輸出時分秒表示的當前時間,格式形如 H H : M M : S S ,其中 H H 表示時,值為 0 到 23 ,M M 表示分,值為 0 到 59,S S 表示秒,值為 0 到 59。時、分、秒不足兩位時補前導 0。
測試樣例1
Input:
46800999
Output:
13:00:00
測試樣例2
Input:
1618708103123
Output:
01:08:23
評測用例規模與約定