2020年B组第三场真题
Posted 揭航
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020年B组第三场真题相关的知识,希望对你有一定的参考价值。
2020年B组第三场
A_数青蛙
问题描述
“一只青蛙一张嘴,两只眼睛四条腿。两只青蛙两张嘴,四只眼睛八条腿。
三只青蛙三张嘴,六只眼睛十二条腿。……二十只青蛙二十张嘴,四十只眼睛八十条腿。”
请问上面这段文字,如果完全不省略,全部写出来,从 1 到 20 只青蛙,总共有多少个汉字。
约定:
数字 2 单独出现读成 “两”,在其他数里面读成 “二”,例如 “十二”。
10 读作 “十”,11 读作 “十一”,22 读作 “二十二”。
请只计算汉字的个数,标点符号不计算。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
答案:353
int get_num(int n) {
if (n >= 1 && n <= 10) { // 1 - 10
return 1;
} else if (n >= 11 && n <= 20 || n % 10 == 0) { // 11 - 20 整十
return 2;
} else {
return 3;
}
}
int res;
int main() {
for (int i = 1; i <= 20; ++i) {
res += get_num(i); // i只青蛙
}
for (int i = 1; i <= 20; ++i) { // i张嘴
res += get_num(i);
}
for (int i = 2; i <= 2 * 20; i += 2) { // i只眼睛
res += get_num(i);
}
for (int i = 4; i <= 4 * 20; i += 4) { // i条腿
res += get_num(i);
}
printf("%d", res + 200); // 除了变量 还有其他固定字符一行10个字,共20行
return 0;
}
B_互质
问题描述
今年是 2020 年,今天是 10 月 18 日。
请问在 1 到 2020 中,有多少个数与 1018 互质。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
答案:1008
int res;
int main() {
for (int i = 1; i <= 2020; ++i) {
if (__gcd(i, 1018) == 1) {
++res;
}
}
printf("%d\\n", res);
return 0;
}
C_车牌
问题描述
A 市的车牌由六位组成,其中前三位可能为数字 0 至 9,或者字母 A 至 F,每位有 16 种可能。
后三位只能是数字 0 至 9。为了减少攀比,车牌中不能有连续三位是相同的字符。
例如,202020 是合法的车牌,AAA202 不是合法的车牌,因为前三个字母相同。
请问,A 市有多少个合法的车牌?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
答案:4002750
int res;
int n = 6;
vector<int> path;
void dfs(int idx) {
if (idx == n) {
bool flag = true;
// 连续三项不能重复
for (int i = n - 1; i >= 2; --i) {
if (path[i] == path[i - 1] && path[i - 1] == path[i - 2]) {
flag = false;
break;
}
}
if (flag) {
++res;
}
return;
}
// 前3项 0 - 9
if (idx <= 2) {
for (int i = 0; i <= 15; ++i) {
path.push_back(i);
dfs(idx + 1);
path.pop_back();
}
} else {
for (int i = 0; i <= 9; ++i) {
path.push_back(i);
dfs(idx + 1);
path.pop_back();
}
}
}
int main() {
dfs(0);
printf("%d\\n", res);
return 0;
}
D_Fibonacci 集合
问题描述
小蓝定义了一个 Fibonacci 集合 F,集合的元素如下定义:
最小的 5 个 Fibonacci 数 1, 2, 3, 5, 8 属于集合 F。
如果一个元素 x 属于 F,则 3x + 2、5x + 3 和 8x + 5 都属于集合 F。
其他元素都不属于 F。
请问,这个集合中的第 2020 小元素的值是多少?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
41269
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <set>
using namespace std;
// 要小的在前面才行
priority_queue<int, vector<int>, greater<int> > qe;
set<int> se;
int main() {
se.insert(1);
se.insert(2);
se.insert(3);
se.insert(5);
se.insert(8);
qe.push(1);
qe.push(2);
qe.push(3);
qe.push(5);
qe.push(8);
while (qe.size()) {
int x = qe.top();
qe.pop();
// 用过了就不要再用了
if (!se.count(3 * x + 2)) {
qe.push(3 * x + 2);
se.insert(3 * x + 2);
}
if (!se.count(5 * x + 3)) {
qe.push(5 * x + 3);
se.insert(5 * x + 3);
}
if (!se.count(8 * x + 5)) {
qe.push(8 * x + 5);
se.insert(8 * x + 5);
}
// 数据个数要大,不能只是到2025,还有更小得
if (se.size() >= 1e6) {
break;
}
}
int idx = 1;
set<int>::iterator it = se.begin();
for (it; it != se.end(); ++it) {
if (idx >= 2025) {
break;
}
printf("%d %d\\n", idx, *it);
idx++;
}
return 0;
}
E_上升子串
问题描述
小蓝有一个字母矩阵,他喜欢和小伙伴们在这个矩阵上玩一些游戏。
今天,他打算玩找上升子串的游戏,游戏是合作性质的。小蓝和小伙伴们首先要在矩阵中指定一个位置,
然后从这个位置开始,向上下左右相邻位置移动,移动必须满足所到达位置上的字母比当前位置大。
小蓝和小伙伴们可以移动任意多次,也可以随时停下来,这样就找到了一个上升子串。
只要子串在矩阵中的位置不同,就认为是不同的子串。
小蓝想知道,一共可以找到多少个上升子串。
小蓝的矩阵很大,已经放在了试题目录下面,叫 inc.txt。
为了更清楚的描述问题,他还找了一个很小的矩阵用来解释。例如,对于矩阵:
AB
BC
1
2
可以找到 4 个长度为 1 的上升子串、4 个长度为 2 的上升子串、2 个长度为 3 的上升子串,共 10 个。
现在,请你对于小蓝的大矩阵,找到上升子串的数量。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
F_日期识别
题目描述
小蓝要处理非常多的数据,其中有一些数据是日期。
在小蓝处理的日期中有两种常用的形式:英文形式和数字形式。
英文形式:
每个月的英文的前三个字母作为月份标识,后面跟两位数字表示日期,
月份标识第一个字母大写,后两个字母小写,日期小于 10 时要补前导 0。
1 月到 12 月英文的前三个字母分别是 Jan、Feb、Mar、Apr、May、Jun、Jul、Aug、Sep、Oct、Nov、Dec。
数字形式:
直接用两个整数表达,中间用一个空格分隔,两个整数都不写前导 0。
其中月份用 1 至 12 分别表示 1 月到 12 月。
输入一个日期的英文形式,请输出它的数字形式。
输入格式
输入一个日期的英文形式。
输出格式
输出一行包含两个整数,分别表示日期的月和日。
输入样例1
Feb08
输出样例1
2 8
输入样例2
Oct18
输出样例2
10 18
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
string month[15] = {"0", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int str2int(string str) {
int ans = 0;
for (int i = 0; i < str.size(); ++i) {
ans = ans * 10 + (str[i] - '0');
}
return ans;
}
int main() {
string str;
cin >> str;
string sub_str1 = str.substr(0, 3);
for (int i = 1; i <= 12; ++i) {
if (month[i] == sub_str1) {
printf("%d ", i);
break;
}
}
string sub_str2 = str.substr(3, 2);
int num = str2int(sub_str2);
printf("%d ", num);
return 0;
}
G_乘法表
题目描述
九九乘法表是学习乘法时必须要掌握的。
在不同进制数下,需要不同的乘法表,例如,四进制下的乘法表如下所示:
1*1=1
2*1=2 2*2=10
3*1=3 3*2=12 3*3=21
请注意,乘法表中两个数相乘的顺序必须为样例中所示的顺序,不能随意交换两个乘数。
给定 P,请输出 P 进制下的乘法表。
输入格式
输入一个整数 P。
输出格式
输出 P 进制下的乘法表。
P 进制中大于等于 10 的数字用大写字母 A、B、C、⋯ 表示。
输入样例1
4
输出样例1
1*1=1
2*1=2 2*2=10
3*1=3 3*2=12 3*3=21
输入样例2
8
输出样例2
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=11
4*1=4 4*2=10 4*3=14 4*4=20
5*1=5 5*2=12 5*3=17 5*4=24 5*5=31
6*1=6 6*2=14 6*3=22 6*4=30 6*5=36 6*6=44
7*1=7 7*2=16 7*3=25 7*4=34 7*5=43 7*6=52 7*7=61
数据范围
2 ≤ P ≤ 36
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
int p;
char a[100]; // 存0-9 A-Z字符
// a[] = {'0', ....., 'A', ..., 'Z'};
// P进制乘法
// 10 * 10 = 100
// A * A =
string get_ans(int x, int p) {
string ans = "";
while (x) {
char ch = a[x % p];
ans = ans + ch;
x /= p;
}
reverse(ans.begin(), ans.end());
return ans;
}
/*
P < 10
string ans = "";
while (x) {
char ch = x % p + '0';
ans = ans + ch;
x /= p;
}
reverse(ans.begin(), ans.end());
*/
int main() {
scanf("%d", &p);
// 初始化
for (int i = 0; i <= 9; ++i) {
a[i] = i + '0';
}
for (int i = 10; i <= 35; ++i) {
a[i] = i - 10 + 'A';
}
for (int i = 1; i <= p; ++i) {
for (int j = 1; j <= i; ++j) {
printf("%c*%c=", a[i], a[j]);
cout << get_ans(i * j, p) << " ";
}
puts("");
}
// cout << get_ans(5*5, p);
return 0;
}
11
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=11 4*4=15
5*1=5 5*2=A 5*3=14 5*4=19 5*5=23
6*1=6 6*2=11 6*3=17 6*4=22 6*5=28 6*6=33
7*1=7 7*2=13 7*3=1A 7*4=26 7*5=32 7*6=39 7*7=45
8*1=8 8*2=15 8*3=22 8*4=2A 8*5=37 8*6=44 8*7=51 8*8=59
9*1=9 9*2=17 9*3=25 9*4=33 9*5=41 9*6=4A 9*7=58 9*8=66 9*9=74
A*1=A A*2=19 A*3=28 A*4=37 A*5=46 A*6=55 A*7=64 A*8=73 A*9=82 A*A=91
B*1=10 B*2=20 B*3=30 B*4=40 B*5=50 B*6=60 B*7=70 B*8=80 B*9=90 B*A=A0 B*B=100
I_画中漂流
题目描述
在梦境中,你踏上了一只木筏,在江上漂流。
根据对当地的了解,你知道在你下游 D 米处有一个峡谷,如果你向下游前进大于等于 D 米则必死无疑。
现在你打响了急救电话,T 秒后救援队会到达并将你救上岸,水流速度是 1 米/秒,你现在有 M 点体力。
每消耗一点体力,你可以划一秒桨使船向上游前进 1 米,否则会向下游前进 1 米(水流),M 点体力需在救援队赶来前花光。
因为江面太宽了,凭借你自己的力量不可能上岸,请问,有多少种划桨的方案可以让你得救。
两个划桨方案不同是指:存在某一秒钟,一个方案划桨,另一个方案不划。
输入格式
输入一行包含三个整数 D, T, M。
输出格式
输出一个整数,表示可以让你得救的总方案数,答案可能很大,请输出方案数除以 1,000,000,007 的余数。
输入样例
1 6 3
输出样例
5
数据范围
对于 50% 的评测用例,1 ≤ T ≤ 350
对于所有评测用例,1 ≤ T ≤ 3000 , 1 ≤ D ≤ T , 1 ≤ M ≤ 1500 1≤T≤3000
DFS 超时了
const int MOD = 1e9 + 7;
int D, T, M;
int res;
void dfs(int D, int T, int M) {
if (T == 0) {
res = (res + 1) % MOD;
return;
}
if (M >= 1) { // 划桨 向前
dfs(D + 1, T - 1, M - 1);
}
// 大于D米就不行了,就是D减少到0 等于 0 就死了
// 不划桨
if (D > 1) {
dfs(D - 1, T - 1, M);
}
}
int main() {
scanf("%d%d%d", &D, &T, &M);
dfs(D, T, M);
printf("%d\\n", res);
return 0;
}
记忆化搜索
const int MOD = 1e9 + 7;
int D, T, M;
int f[3015][1515];
int dfs(int D, int T, int M) {
if (f[T][M] != -1) { // 已经搜索过了
return f[T][M];
}
if (T == 0) {
if (M) {
return 0;
}
return f[0][0] = 1;
}
f[T][M] = 0;
if (M > 0) {
f[T][M] = (f[T][M] + dfs(D + 1, T - 1, M - 1)) % MOD;
}
if (D > 1) {
f[T][M] = (f[T][M] + dfs(D - 1, T - 1, M)) % MOD;
}
return f[T][M];
}
int main() {
memset(f, -1, sizeof f);
scanf("%d%d%d", &D, &T, &M);
printf("%d\\n", dfs(D, T, M));
return 0;
}
以上是关于2020年B组第三场真题的主要内容,如果未能解决你的问题,请参考以下文章