首先,因为是第一次参赛(我们学校比较坑,大一不能参赛),所以以前不是很了解蓝桥杯的题目模式。随着做了几年的真题,发现蓝桥杯似乎有一种暴力求解的魔力,很多题目都可以通过暴力求解,例如第七届的第7题的剪邮票。所以又称为暴力杯,但是第九届的题目又有点难度,所以心中还是对蓝桥杯的难度存在疑虑。
最后及其不幸的是,第十届的蓝桥杯题目不是很难,填空题基本没有难度,编程题“看上去”也不是很难,然后。。我就理所当然的GG了,拿了个省二就当作陪跑了。。(很沮丧,其实算了分数就差一点)。
第一题:
作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员,组成球队的首发阵容。
每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1 号位至 5 号位的评分之和最大可能是多少?
分析:这题用暴力可以做,但是数据量不大,手算花不了多久就能计算出来,并且可以验证最优解。
答案:490
第二题:年号字串
小明用字母A 对应数字1,B 对应2,以此类推,用Z 对应26。对于27以上的数字,小明用两位或更长位的字符串来对应,例如AA 对应27,AB 对应28,AZ 对应52,LQ 对应329。
请问2019 对应的字符串是什么?
分析:这题也是可以手算的,因为他是特殊的26进制(不是0-25,而是1-26),所以需要注意的就是边界的进位。
答案:BYQ
第三题:数列求值
给定数列1, 1, 1, 3, 5, 9, 17, …,从第4 项开始,每项都是前3 项的和。求
第20190324 项的最后4 位数字。
分析:这题注意每算完一项就对10000取模,就可以顺利得到答案。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3*1e7+5;
const int mod = 1e4;
int f[N];
int main()
{
f[1] = f[2] = f[3] = 1;
for(int i = 4; i <= 20190324; i++)
f[i] = ((f[i-3]+f[i-2])%mod+f[i-1])%mod;
cout << f[20190324];
}
答案:4659
第四题:数的分解
把2019 分解成3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
注意交换3个整数的顺序被视为同一种方法,例如1000+1001+18 和 1001+1000+18 被视为同一种。
分析:这道题注意i<j<k不要重复计算,是一道简单的组合题。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2500;
int a[N], vis[N];
int n, k, ans;
int check(int n)
{
while(n >= 1)
{
if(n%10 == 2 || n%10 == 4)
return 0;
n /= 10;
}
return 1;
}
void DFS(int pre, int cur, int sum)
{
if(cur == 3 && sum == n)
{
ans++;
return;
}
if(cur >= 3) return;
for(int i = pre+1; i < k; i++)
{
if(!vis[a[i]])
{
vis[a[i]] = 1;
DFS(i, cur+1, sum+a[i]);
vis[a[i]] = 0;
}
}
}
int main()
{
ans = k = 0;
for(int i = 1; i <= 2016; i++)
if(check(i))
a[k++] = i;
cin >> n;
DFS(-1, 0, 0);
cout << ans;
}
第五题:迷宫
下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可以通行的地方。
010000
000100
001001
110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这个它的上、下、左、右四个方向之一。
对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫,一共10 步。其中D、U、L、R 分别表示向下、向上、向左、向右走。对于下面这个更复杂的迷宫(30 行50 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。请注意在字典序中D<L<R<U。
分析:这道题BFS和DFS都可以,我用的是BFS,因为我DFS比较烂。。算是一道裸题吧,不难。
代码:
#include <bits/stdc++.h>
using namespace std;
struct node {
int x, y;
string p;
};
char s[35][55];
int vis[35][55], n, m;
char d[] = {'D', 'L', 'R', 'U'};
int dx[] = {1, 0, 0, -1};
int dy[] = {0, -1, 1, 0};
int check(int x, int y)
{
if(x>=0 && x<n && y>=0 && y<m && !vis[x][y] && s[x][y]=='0')
return 1;
return 0;
}
void BFS(int x, int y)
{
node now, next;
queue<node>q;
q.push(node{x, y, ""});
while(!q.empty())
{
now = q.front();
q.pop();
if(now.x == n-1 && now.y == m-1)
{
cout << now.p;
exit(0);
}
for(int i = 0; i < 4; i++)
{
next = now;
next.x += dx[i];
next.y += dy[i];
if(check(next.x, next.y))
{
vis[next.x][next.y] = 1;
next.p += d[i];
q.push(next);
}
}
}
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i++)
scanf("%s", s[i]);
memset(vis, 0, sizeof(vis));
vis[0][0] = 1;
BFS(0, 0);
}
/*
4 6
010000
000100
001001
110000
*/
/*
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
第六题:特别数的和
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导0),在1 到 40 中这样的数包括1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。请问,在 1 到n 中,所有这样的数的和是多少?
【输入格式】
输入一行包含两个整数n。
【输出格式】
输出一行,包含一个整数,表示满足条件的数的和。
【样例输入】
40
【样例输出】
574
【评测用例规模与约定】
对于20% 的评测用例,1≤n≤10。
对于50% 的评测用例,1≤n≤100。
对于80% 的评测用例,1≤n≤1000。
对于所有评测用例,1≤n≤10000。
分析:这道题就是第四题的编程题,思路就跟第四题一样。
代码:
#include <bits/stdc++.h>
using namespace std;
int check(int n)
{
while(n >= 1)
{
if(n%10==2 || n%10==0 || n%10==1 || n%10==9)
return 1;
n /= 10;
}
return 0;
}
int main()
{
int n, sum = 0;
cin >> n;
for(int i = 1; i <= n; i++)
if(check(i))
sum += i;
cout << sum;
}
第七题:完全二叉树的权值
给定一棵包含N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是A1,A2,...,AN ,如下图所示:
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是1。
【输入格式】
第一行包含一个整数N。
第二行包含N 个整数A1,A2,...,AN
【输出格式】
输出一个整数代表答案。
【样例输入】
7
1 6 5 4 3 2 1
【样例输出】
2
分析:因为是完全二叉树,遍历每一层的和就行了,需要注意的一点是:在设置最大值初值时,不能设为0!因为有可能是负数。我比赛的时候就死在这里了,因为我已经形成习惯了。。也是因为这题无缘省一,很心疼。。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const ll MAXN = 1e5+5;
ll a[MAXN];
int main()
{
int n, ans, d, ind;
ll Max = -INF, sum;
ind = ans = d = 1;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
int t = n;
while(n > 0)
{
sum = 0;
for(int i = ind; i < min(t + 1, 1<<d); i++)
sum += a[i];
if(sum > Max)
{
Max = sum;
ans = d;
}
n -= ind;
ind += 1<<d-1;
d++;
}
cout << ans;
}
第八题:等差数列
数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中N 个整数。
现在给出这N 个整数,小明想知道包含这N 个整数的最短的等差数列有几项?
【输入格式】
输入的第一行包含一个整数N。
第二行包含N 个整数A1,A2,...,AN(注意A1~AN并不一定是按等差数列中的顺序给出)
【输出格式】
输出一个整数表示答案。
【样例输入】
5
2 6 4 10 20
【样例输出】
10
【样例说明】
包含2、6、4、10、20 的最短的等差数列是2、4、6、8、10、12、14、16、18、20。
【评测用例规模与约定】
对于所有评测用例,2≤N≤100000, 0≤Ai≤10^9
分析:对所有数字排序,计算相邻的数的差,公差就是公共的差,由此可以想到GCD。
需要注意的是:d可能=0!这时候就是常数项,直接输出N即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int a[N], d[N];
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
int main()
{
int n, p, ans;
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i];
sort(a, a+n);
for(int i = 1; i < n; i++)
d[i-1] = a[i]-a[i-1];
p = d[0];
if(!p) printf("%d", n);
else
{
for(int i = 1; i < n-1; i++)
p = gcd(p, d[i]);
ans = (a[n-1] - a[0]) / p + 1;
cout << ans;
}
}
第九题:后缀表达式
给定N 个加号、M 个减号以及N + M + 1 个整数A1,A2,...,AM+N+1,小明想知道由这些组成的后缀表达式的值最大为多少?
本次大赛最坑的题目出现了!!!
很多人用贪心做,排序完把前面N+1个数加起来-后M个数。
但是
后缀表达式是可以在任意地方加括号的!
分析:如果没有减号,显而易见把所有数加起来,如果有减号,因为-(-)就等于-和+,-(-(-)等于+和-(这里的+指的是加上一个数的绝对值),所以如果有减号,最后就可以利用括号转换成一个减号。
代码:
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
const int N = 1e5+5;
int a[2*N+5];
int main()
{
int n, m, Min, Max;
cin >> n >> m;
Min = inf;
Max = -inf;
for (int i = 0; i <= n+m; i++)
{
cin >> a[i];
Min = min(Min, a[i]);
Max = max(Max, a[i]);
}
ll ans = 0;
if(m)
{
for(int i = 0; i <= n+m; i++)
ans += abs(a[i]);
if(Min > 0) ans -= Min * 2;
if(Max < 0) ans += Max * 2;
}
else for (int i = 0; i <= n+m; i++)
ans += a[i];
cout << ans << endl;
return 0;
}
第十题:略略略。