2020第十一届蓝桥杯软件类省赛第二场C/C++ 大学 B 组(题解)
試題 A: 門牌制作
問題描述
小藍(lán)要為一條街的住戶制作門牌號(hào)。
這條街一共有 2020 位住戶,門牌號(hào)從 1 到 2020 編號(hào)。
小藍(lán)制作門牌的方法是先制作 0 到 9 這幾個(gè)數(shù)字字符,最后根據(jù)需要將字
符粘貼到門牌上,例如門牌 1017 需要依次粘貼字符 1、 0、 1、 7,即需要 1 個(gè)
字符 0, 2 個(gè)字符 1, 1 個(gè)字符 7。
請(qǐng)問要制作所有的 1 到 2020 號(hào)門牌,總共需要多少個(gè)字符 2?
直接暴力
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int ans = 0;for(int i = 1; i <= 2020; i++) {int temp = i;while(temp) {if(temp % 10 == 2) ans++;temp /= 10;}}printf("%d\n", ans);return 0; } /* 624 */試題 B: 既約分?jǐn)?shù)
【問題描述】
如果一個(gè)分?jǐn)?shù)的分子和分母的最大公約數(shù)是 1,這個(gè)分?jǐn)?shù)稱為既約分?jǐn)?shù)。
例如,34,52,18,71\frac{3}{4}, \frac{5}{2}, \frac{1}{8}, \frac{7}{1}43?,25?,81?,17?都是既約分?jǐn)?shù)。
請(qǐng)問,有多少個(gè)既約分?jǐn)?shù),分子和分母都是 1 到 2020 之間的整數(shù)(包括 1
和 2020)?
顯然這不是一道簡(jiǎn)單題,我們寫下數(shù)學(xué)式子來
∑i=1n∑j=1n[gcd(i,j)=1]∑k=1nμ(k)∑i=1nk∑j=1nk\sum_{i = 1} ^{n} \sum_{j = 1} ^{n} [gcd(i, j) = 1]\\ \sum_{k = 1} ^{n} \mu(k) \sum_{i = 1} ^{\frac{n}{k}} \sum_{j = 1} ^{\frac{n}{k}}\\ i=1∑n?j=1∑n?[gcd(i,j)=1]k=1∑n?μ(k)i=1∑kn??j=1∑kn??
然后就只要線性篩,加數(shù)論分塊即可。
試題 C: 蛇形填數(shù)
如下圖所示,小明用從 1 開始的正整數(shù)“蛇形”填充無限大的矩陣。
1 2 6 7 15 :::
3 5 8 14 :::
4 9 13 :::
10 12 :::
11 :::
:::
容易看出矩陣第二行第二列中的數(shù)是 5。請(qǐng)你計(jì)算矩陣中第 20 行第 20 列
的數(shù)是多少 ?
這題也是模擬即可,所以就直接上代碼吧,看代碼就懂了。
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;int a[50][50];int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n = 45, num = 45 * 45;for(int i = 1, cnt = 1; i <= n && cnt <= num; i++) {if(i & 1) {for(int x = i, y = 1; x >= 1 && y <= i; x--, y++) {a[x][y] = cnt++;}}else {for(int x = 1, y = i; x <= i && y >= 1; x++, y--) {a[x][y] = cnt++;}}}printf("%d\n", a[20][20]);return 0; } /* 761 */試題 D: 跑步鍛煉
【問題描述】
小藍(lán)每天都鍛煉身體。
正常情況下,小藍(lán)每天跑 1 千米。如果某天是周一或者月初(1 日),為了
激勵(lì)自己,小藍(lán)要跑 2 千米。如果同時(shí)是周一或月初,小藍(lán)也是跑 2 千米。
小藍(lán)跑步已經(jīng)堅(jiān)持了很長(zhǎng)時(shí)間,從 2000 年 1 月 1 日周六(含)到 2020 年
10 月 1 日周四(含)。請(qǐng)問這段時(shí)間小藍(lán)總共跑步多少千米?
按照天數(shù)去模擬就OK了。
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int a = 2000, b = 1, c = 1, num = 1, ans = 0;while(a != 2020 || b != 10 || c != 2) {if(c == 1 || num % 7 == 3) ans += 2;else ans += 1;int nowday = day[b];if((a % 400 == 0 || (a % 4 == 0 && a % 100 != 0)) && b == 2) nowday++;c++, num++;if(c > nowday) {c = 1;b += 1;}if(b == 13) {a += 1;b = 1;}}printf("%d\n", ans);return 0; } /* 8879 */試題 E: 七段碼
總共有7根管子,二進(jìn)制枚舉,然后bfs或者dfs判斷是否聯(lián)通即可。
下面用0 -> a, 1 -> b……6 -> g,也就是用0代表a,以此類推,,
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;bool judge(int pos, int value) {queue<int> q;q.push(pos);value ^= 1ll << pos;while(q.size()) {int temp = q.front();q.pop();if(temp == 0) {if(value >> 1 & 1) {value ^= 1 << 1;q.push(1);}if(value >> 5 & 1) {value ^= 1 << 5;q.push(5);}}else if(temp == 1) {if(value >> 0 & 1) {value ^= 1 << 0;q.push(0);}if(value >> 2 & 1) {value ^= 1 << 2;q.push(2);}if(value >> 6 & 1) {value ^= 1 << 6;q.push(6);}}else if(temp == 2) {if(value >> 1 & 1) {value ^= 1 << 1;q.push(1);}if(value >> 3 & 1) {value ^= 1 << 3;q.push(3);}if(value >> 6 & 1) {value ^= 1 << 6;q.push(6);}}else if(temp == 3) {if(value >> 2 & 1) {value ^= 1 << 2;q.push(2);}if(value >> 4 & 1) {value ^= 1 << 4;q.push(4);}}else if(temp == 4) {if(value >> 3 & 1) {value ^= 1 << 3;q.push(3);}if(value >> 5 & 1) {value ^= 1 << 5;q.push(5);}if(value >> 6 & 1) {value ^= 1 << 6;q.push(6);}}else if(temp == 5) {if(value >> 0 & 1) {value ^= 1 << 0;q.push(0);}if(value >> 4 & 1) {value ^= 1 << 4;q.push(4);}if(value >> 6 & 1) {value ^= 1 << 6;q.push(6);}}else {if(value >> 1 & 1) {value ^= 1 << 1;q.push(1);}if(value >> 2 & 1) {value ^= 1 << 2;q.push(2);}if(value >> 4 & 1) {value ^= 1 << 4;q.push(4);}if(value >> 5 & 1) {value ^= 1 << 5;q.push(5);}}}return value == 0; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int ans = 0;for(int i = 1; i < 1 << 7; i++) {int j;for(j = 0; j < 7; j++) {if(i >> j & 1) {break;}}if(judge(j, i)) {ans++;}}printf("%d\n", ans);return 0; } /* 80 */試題 F: 成績(jī)統(tǒng)計(jì)
統(tǒng)計(jì)≥60\geq 60≥60和≥85\geq 85≥85的數(shù)量,然后按照要求四舍五入即可。
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n, a, res = 0, ans = 0;scanf("%d", &n);for(int i = 1; i <= n; i++) {scanf("%d", &a);if(a >= 60) res++;if(a >= 85) ans++;}printf("%.0f%%\n%.0f%%\n", (double)res * 100.0 / n, (double)ans * 100.0 / n);return 0; }試題 G: 回文日期
跟D題一樣,按照天數(shù)模擬,然后再judge就行了。
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};bool judge1(int a, int b, int c) {int d = a * 10000 + b * 100 + c;int num[10], cnt = 9;while(d) {num[--cnt] = d % 10;d /= 10;}for(int l = 1, r = 8; l < r; l++, r--) {if(num[l] != num[r]) {return false;}}return true; }bool judge2(int a, int b, int c) {int d = a * 10000 + b * 100 + c;int num[10], cnt = 9;while(d) {num[--cnt] = d % 10;d /= 10;}for(int l = 1, r = 8; l < r; l++, r--) {if(num[l] != num[r] || num[l] != num[l & 1 ? 1 : 2]) {return false;}}return true; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int a, b, c, d, flag = 0;scanf("%d", &d);a = d / 10000, b = (d / 100) % 100, c = d % 100;while(flag < 2) {int nowday = day[b];if(((a % 400 == 0) || (a % 4 == 0 && a % 100 != 0)) && b == 2) nowday++;c++;if(c > nowday) {c = 1;b += 1;}if(b == 13) {a += 1;b = 1;}if(!flag && judge1(a, b, c)) {printf("%d%02d%02d\n", a, b, c);flag += 1;}if(judge2(a, b, c)) {printf("%d%02d%02d\n", a, b, c);flag += 1;}}return 0; }試題 H: 子串分值和
這題稍微有點(diǎn)思維吧,我們定義,對(duì)于一個(gè)字符串我們只記錄這個(gè)字母在這個(gè)字符中出現(xiàn)的第一次有貢獻(xiàn),
接下來就是統(tǒng)計(jì),以某個(gè)字符為第一次出現(xiàn)的字母的字串?dāng)?shù)量了,
我們定義last[i]last[i]last[i]表示字符iii在當(dāng)前枚舉點(diǎn)之前最后一次出現(xiàn)的位置,顯然這個(gè)字符的左端點(diǎn)就可以落在[last[i]+1,now][last[i] + 1, now][last[i]+1,now]
這個(gè)區(qū)間了,然后右端點(diǎn)可以在now,nnow, nnow,n區(qū)間,所有的字串就是這兩個(gè)長(zhǎng)度的乘積,然后就是非常簡(jiǎn)短的代碼了。
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 1e5 + 10;int last[30], n;char str[N];int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);scanf("%s", str + 1);n = strlen(str + 1);ll ans = 0;for(int i = 1; i <= n; i++) {ans += 1ll * (i - last[str[i] - 'a']) * (n - i + 1);last[str[i] - 'a'] = i;}printf("%lld\n", ans);return 0; }試題 I: 平面切分
平面上有 N 條直線,其中第 i 條直線是y=Ai?x+Biy = A_i · x + B_iy=Ai??x+Bi?。
請(qǐng)計(jì)算這些直線將平面分成了幾個(gè)部分。
試題 J: 字串排序
【問題描述】
小藍(lán)最近學(xué)習(xí)了一些排序算法,其中冒泡排序讓他印象深刻。
在冒泡排序中,每次只能交換相鄰的兩個(gè)元素。
小藍(lán)發(fā)現(xiàn),如果對(duì)一個(gè)字符串中的字符排序,只允許交換相鄰的兩個(gè)字符,
則在所有可能的排序方案中,冒泡排序的總交換次數(shù)是最少的。
例如,對(duì)于字符串 lan 排序,只需要 1 次交換。對(duì)于字符串 qiao 排序,
總共需要 4 次交換。
小藍(lán)的幸運(yùn)數(shù)字是 V,他想找到一個(gè)只包含小寫英文字母的字符串,對(duì)這
個(gè)串中的字符進(jìn)行冒泡排序,正好需要 V 次交換。請(qǐng)幫助小藍(lán)找一個(gè)這樣的字
符串。如果可能找到多個(gè),請(qǐng)告訴小藍(lán)最短的那個(gè)。如果最短的仍然有多個(gè),
請(qǐng)告訴小藍(lán)字典序最小的那個(gè)。請(qǐng)注意字符串中可以包含相同的字符。
思路
顯然要使長(zhǎng)度最短,我們就不能浪費(fèi)每一個(gè)字母,所以,一定有字母是遞減的順序的,
要使字典序最短,每個(gè)字母出現(xiàn)的數(shù)量一定是要從前往后遞增的,這樣就好了,,
限制一下每個(gè)字母最多出現(xiàn)的次數(shù)然后就是dfsdfsdfs爆搜,
但是考場(chǎng)上限制的次數(shù)太小了,寫了777,只能測(cè)到910009100091000左右的測(cè)試點(diǎn),改到888就好了。
(這題貌似好像有點(diǎn)問題,并不是正解 >_<)
/*Author : lifehappy */ #include <bits/stdc++.h>using namespace std;const int N = 1e4 + 10;char ans[N], res[N];int n, len;bool judge() {int i = len;while(ans[i] == res[i] && i) i--;return res[i] < ans[i]; }void dfs(int now, int maxn, int m, int sum) {if(sum == n) {if(m < len || (m == len && judge())) {len = m;for(int i = 1; i <= len; i++) {ans[i] = res[i];}}return ;}if(now >= 26) return ;for(int i = 1; i <= maxn; i++) {int temp = sum + m * i;if(temp > n) return ;res[m + i] = char(now + 'a');dfs(now + 1, i, m + i, temp);} }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);len = 0x3f3f3f3f;scanf("%d", &n);dfs(0, 8, 0, 0);for(int i = len; i >= 1; i--) {putchar(ans[i]);}puts("");return 0; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的2020第十一届蓝桥杯软件类省赛第二场C/C++ 大学 B 组(题解)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 体内寒湿气重怎么祛除
- 下一篇: 减肥怎么知道自己减的是脂肪还是肌肉