2019年第十届蓝桥杯C/C++ B组省赛练习
A 组队
解题思路
题目其实有坑,因为一到五号位最大值的话是98+99+99+98+98=493但是这样的话就入坑了,因为17号选手很牛皮,是1,3,4号位的第一,但他只能是一个人占一个坑,就这三个情况分情况讨论
其他位数的选手都是没啥冲突的
17号选手按1号位算: 98+99+98+97+98=490
17号选手按3号位算: 97+99+99+97+98=490
17号选手按4号位算: 97+99+98+98+98=490
答案:490 写代码反而麻烦
B 年号字串
解题思路
很明显,题目中这个对应的是27进制的转换
自己记忆一下以前进制转换的时候都是除一下,取余数,最后余数倒着就是目标进制的大小
不多说上代码。
代码
#include<bits/stdc++.h>
using namespace std;
/*
2019
BYQ
*/
int main()
{
int x,t=0; //t作为位数指针
int a[100]; //存放数字 最后记得倒置
cin >> x;
while (x)
{
a[t++] = x % 26; //存一位,t++,最后有t位 是从0-t-1
x /= 26;
}
for (int i = t - 1; i >= 0; i--)
{
cout << char('A' + a[i] - 1); //这里减-1,可以想象下余数是1其实对应A,A在加一就是b了所以得减回来
}
}
或者
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,t;
char c;
cin>>n;
vector<char> v;
while(n)
{
t=n%26;
if(t==0){
c='Z';
}
else{
c='A'+t-1;
}
v.push_back(c);
n/=26;
}
for(int i=v.size()-1;i>=0;i--)
{
cout<<v[i];
}
}
C 数列求值
解题思路
简单题,就是得取模10000,要不然数太大了,会越界,因为最后要的只是最后四位, 所以只搞最后四位即可,超过四位的部分其实是多余的运算,
代码
#include<bits/stdc++.h>
using namespace std;
/*
4659
*/
typedef long long ll;
ll dp[20199999];
int main()
{
dp[1] = dp[2] = dp[3] = 1;
for (int i = 4; i <= 20190324; i++)
{
dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3])%10000; //动态规划
}
cout << dp[20190324] << endl;
return 0;
}
D 数的分解
题目分析
代码挺简单的看代码就可
代码
#include<bits/stdc++.h>
using namespace std;
/*
40785
*/
typedef long long ll;
ll ans = 0;
int t;
bool judge(int x) //检查看看数合法不
{
while (x)
{
t = x % 10;
if (t == 2 || t == 4) return 0;
x /= 10;
}
return 1;
}
int main()
{
for (int i = 1; i <= 673; i++) //最小的 2019/3=673 所以第一个数最大673
{
if (!judge(i)) continue; //随时continue,降低复杂度,提高运行速度
for (int j = i+1; j < 1010; j++) //第三个数比第二个数大,所以第二个书最大也就2019的一半,我门保守估计1010
{
if (!judge(j)) continue;
for (int k = j + 1; k < 2019; k++) //第三个最大
{
if (!judge(k)) continue;
if (i + j + k == 2019) ans++;
}
}
}
cout << ans<< endl; //40785
return 0;
}
E 迷宫
解题思路
bfs,记住要以dlru即下左右上的遍历顺序
代码
#include<bits/stdc++.h>
using namespace std;
/* 测试数据 迷宫
30 50
01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000
输出
DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
*/
string mp[55];
bool vis[55][55];
struct node {
int x;
int y;
int step=0;
string str=""; //步数
};
int dx[] = { 1,0,0,-1 };//下 左 右 上
int dy[] = { 0,-1,1,0 };//down left right up
int n, m;
char dir[4] = { 'D','L','R','U' };
bool check(int x, int y)
{
if (x < 0 || x >= n || y < 0 || y >= m||vis[x][y]||mp[x][y]=='1') return 0; //越界
else
return 1;
}
int bfs(int x, int y)
{
queue<node> q;
node nodee;
nodee.x = x, nodee.y = y;
vis[x][y] = 1;
q.push(nodee);
while (!q.empty())
{
node now, temp;
now = q.front();
if (now.x == n - 1 && now.y == m - 1)
{
cout << now.str << endl;
//cout << now.step << endl; //题目没有让输出步数
break;
}
q.pop();
for (int i = 0; i < 4; i++)
{
int xx = now.x + dx[i];
int yy = now.y + dy[i];
if (check(xx, yy)) {//合法的话
temp.x = xx;
temp.y = yy;
temp.step = now.step+1;
temp.str = now.str + dir[i];
q.push(temp);
vis[xx][yy] = 1;
}
}
}
return -1;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> mp[i];
}
bfs(0, 0);
return 0;
}
F 特别数的和
解题思路
逐个遍历检查求和
代码
#include <bits/stdc++.h>
using namespace std;
/*
shuru:40
shuchu:574
*/
bool check(int x) {
int res = 0;
while (x) {
res = x % 10;
if (res == 0 || res == 1 || res == 2 || res == 9) return 1;
x /= 10;
}
return 0;
}
int main() {
int n;
cin >> n;
int ans = 0;
for (int i = 1; i <= n; i++) {
if (check(i)) {
ans += i;
}
}
cout << ans << endl;
return 0;
}
G 完全二叉树的权值
题目思路
解题思路
题目可知,结点最多有100000个,我们假设一个满二叉树,其结点数量之和2的n次方-1到大于100000的话n等于17,也就是说最多17层
我们知道2的16次方-1是65535
也就是说题目中最多也就是16层满的然后17层没满
先看看最多几层,同时有没有达到正好满,在由此分情况讨论
讨论时候,要注意,每一层起点终点可以自己画一个树看看,最左边总是1 2 4 8 最右边则是 1 3 7 15
树每一层起点是pow(2, i - 1),终点是pow(2, i) - 1
代码
#include <bits/stdc++.h>
using namespace std;
/*
shuru:
7
1 6 5 4 3 2 1
shuchu:2
*/
int a[100001] = { 0 };
int ans = 0,anss,sum;//ans代表权值 anss代表对应层数
int main() {
int n;
int floor,yu=0;//floor是其最大层数 yu表示最大层是不是没满=0代表没满
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i < 17; i++)
{
if (pow(2, i) - 1 == n) { //正好存满了
floor = i;
yu = 1; break;
}
if (pow(2, i) - 1 > n) { //有余数 第i层没满
floor = i;
break;
}
}
ans = a[1];//第一层就一个数
anss = 1;
if (yu == 1) { //正好存满
for (int i = 2; i <= floor; i++) //从第二层开始比
{
sum = 0;//初始化sum
for (int j = pow(2, i - 1); j <= pow(2, i) - 1; j++)
{
sum += a[j];
}
if (sum > ans) { ans = sum; anss = i; }
}
}
else {//最后以层没满
for (int i = 2; i < floor; i++) //从第二层开始比
{
sum = 0;//初始化sum
for (int j = pow(2, i - 1); j <= pow(2, i) - 1; j++)
{
sum += a[j];
}
if (sum > ans) { ans = sum; anss = i; }
}
//看看最后一层
sum = 0;//初始化sum
for (int j = pow(2, floor - 1); j <= n; j++)
{
sum += a[j];
}
if (sum > ans) { ans = sum; anss = floor; }
}
cout << anss << endl;
return 0;
}
等差数列
解题思路
就是找满足全部输入数的最大公差
排序
各位减一下最小的,形成伪公差数组
用gcd函数 寻找同时满足公差数组的哪个最合适的数
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a[10005];
int gcd(int a, int b) { //最大公约数公式
return b == 0 ? a : gcd(b, a % b);
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1); //排序 从小到大 如果下标0-n-1 则sort(a,a+n)
for (int i = 2; i <= n; i++) { //求出各位与最小位数的差
a[i] -= a[1];
}
int d = a[2]; //假设最大公差位这俩倒数第二小的数的差
for (int i = 3; i <= n; i++) { //逐一遍历 看看有更小的没
d = gcd(d, a[i]);
}
if (d == 0) { //说明数列是 2 2 2 2 2 2 这种都一样的
cout << n << endl;
}
else {
cout << a[n] / d + 1 << endl; //最小的数量
}
return 0;
}
I 后缀表达式
后期补
J 灵能传输
例题解析
不会,不看这个了就