蓝桥杯题解
文章目录
前言
这是新手上路的第一篇,对于第一次见这个题的同学希望可以有些帮助,而做过的朋友你们也可以提一提对这篇内容以及对题解思路的提升的意见。虽然这篇内容的真题可能已经很久远的,见烂了,但是还是希望对于所需的同学一些帮助吧。
一、题目(蓝桥杯历届试题-回文数字)
观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的。这样的数字叫做:回文数字。
本题要求你找到一些5位或6位的十进制数字。满足如下要求:
该数字的各个数位之和等于输入的整数。
1.输入格式
一个正整数 n (10< n< 100), 表示要求满足的数位和。
2.输出格式
若干行,每行包含一个满足要求的5位或6位整数。 数字按从小到大的顺序排列。 如果没有满足条件的,输出:-1 。
二、样例输入和输出
输入:
44
输出:
99899
499994
589985
598895
679976
688886
697796
769967
778877
787787
796697
859958
868868
877778
886688
895598
949949
958859
967769
976679
985589
994499
三、解题
1.解题思路
1.首先来看样例
根据六位数的集合可以观察出,把六位数的前三位数单独列出来是(4,8,9),(5,8,9),(7,6,9)这三种集合(排列没有特定的顺序),其余的都是通过每个集合的顺序变化得到的。接下来就是存放,排序,输出
暗藏的规矩:奇数满足的回文数只有五位数,五位数或六位数的限定让给出的数在2~54之间,并且45到54之间的奇数没有可满足的情况。(这个规定可能可以提供别的算法,可能哈)
2.了解大概过程后,进行主要的代码简写(部分代码)。
//查找(以六位数为例子)
for (i = 0; i <= 9; i++) {
for (j = 0; j <= 9; j++) {
for (m = 0; m <= 9; m++) {
if (n == 2 * (i + j + m)) {
// printf("%d%d%d\n", i, j, m);
//这里把找到满足的集合存放(三个数一个集合)
a1[l] = i;
b1[l] = j;
c1[l] = m;
l++;
}
}
}
}
//生成六位数,存放。至于为什么要存放,因为刚写的时候可能考虑会考虑到排序
for (i = 0; i < x; i++) {
s[i] = a[i] * 100000 + b[i] * 10000 + c[i] * 1000 + c[i] * 100 + b[i] * 10 + a[i];
}
//输出
if (x == 0)
printf("-1");
else {
for (i = 0; i < x; i++) {
if (a[i] != 0 )//首个位数为0的话,数字位数就不对了
printf("%d\n", s1[i]);
}
}
这里让每个位数从0开始增加到9,优点在于按照顺序输出回文数数组的时候就已经是从小到大排列了,就不需要排序了(这也是我输出之后才发现的)。这个时候就会觉得代码过于繁杂,易错。那我们就继续看。
2.优化代码
这里教大家一个便捷的位数输出方式
for (i = 0; i <= 9; i++) {
for (j = 0; j <= 9; j++) {
for (m = 0; m <= 9; m++) {
if (N == i + j + m && i != 0) {
printf("%d%d%d%d%d%d\n", i, j, m, m, j, i);
x++;
}
}
}
}
这里是用到printf的拼接输出(就是把每位数按照顺序输出),这样一来就不用来合成数了,也不用利用数组来储存就直接输出了。
3.全部代码
代码如下(示例):
#include <stdio.h>
int main() {
int n, x = 0, m = 0, l = 0;
scanf("%d", &n);
int i = 0, j = 0;
if (n % 2 == 0) {
//偶数
int N = n / 2;
//五位数
for (i = 0; i <= 9; i++) {
for (j = 0; j <= 9; j++) {
for (m = 0; m <= 9; m++) {
if (n == 2 * (i + j) + m && i != 0) {
printf("%d%d%d%d%d\n", i, j, m, j, i);
l++;
}
}
}
}
//六位数
for (i = 0; i <= 9; i++) {
for (j = 0; j <= 9; j++) {
for (m = 0; m <= 9; m++) {
if (N == i + j + m && i != 0) {
printf("%d%d%d%d%d%d\n", i, j, m, m, j, i);
x++;
}
}
}
}
if (l == 0 && x == 0)
printf("-1");
} else {
//奇数且只能是五位数
for (i = 0; i <= 9; i++) {
for (j = 0; j <= 9; j++) {
for (m = 0; m <= 9; m++) {
if (n == 2 * (i + j) + m && i != 0) {
printf("%d%d%d%d%d\n", i, j, m, j, i);
x++;
}
}
}
}
if (x == 0)
printf("-1");
}
}
四、题目( 蓝桥杯2014年第五届真题-分糖果)
、有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
每个小朋友都把自己的糖果分一半给左手边的孩子。
一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
1.输入格式
程序首先读入一个整数N(2< N< 100),表示小朋友的人数。
接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
2.输出格式
要求程序输出一个整数,表示老师需要补发的糖果数。
二、样例输入和输出
输入:
3
2 2 4
输出:
4
三、解题
1.解题思路
1.首先可以依据样例来简单模拟一下流程。
在第一次同学之间分发糖果后(可理解为传递),每个人手里的糖果由2 2 4转变为2 3 3,然后由老师来分糖果转变为2 4 4,这个时候老师已经分发2个糖果。继续传递后糖果数量为3 4 3,这个时候老师只需要在分2个糖果便可以结束。
2.了解大概过程后,进行主要的代码简写即传递过程(for循环实现)。
易错思路的代码实现
开始写的时候会觉得,每个同学的糖果变化就是自己本来的加右边同学的一半减自己的一半
//代码可能是这样的
for (i = 0; i < n - 1; i++) {
a[i] = a[i] + a[i + 1] / 2 - a[i] / 2;
}
但是会忽略了for循环的特点:每个数组并不是同时变化的。
例如:以样例来看。第一个同学变化之后会直接影响到最后一个同学,而题目的意思是每个同学同时进行交换。需要注意的是每一个轮交换的时候都需要考虑这个情况。
//最后的主代码实现(部分代码并不是直接连接在一起的)
int a[n], b[n];
//交换
for (i = 0; i < n - 1; i++) {
if (i==0)
b[0] = a[0];
a[i] = a[i] + a[i + 1] / 2 - a[i] / 2;
}
a[n - 1] = a[n - 1] + b[0] / 2 - a[n - 1] / 2;
2.全部代码
代码如下(示例):
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int a[n], b[n], c = 0, i = 0, count = 0, j = 0;
for (i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
for (i = 0; i < n; i++) {
b[i] = a[i];
}
int flag = 1;
while (flag == 1) {
//交换
for (i = 0; i < n - 1; i++) {
if (i==0)
b[0] = a[0];
a[i] = a[i] + a[i + 1] / 2 - a[i] / 2;
}
a[n - 1] = a[n - 1] + b[0] / 2 - a[n - 1] / 2;
//可以看到每轮交换之后的代码 ,利于发现错误
// for (i = 0; i < n; i++) {
// printf("%3d", a[i]);
// }
//老师发糖
for (i = 0; i < n; i++) {
if (a[i] % 2 != 0) {
a[i] += 1;
count++;
}
}
for (i = 0; i < n; i++) {
if (a[0] == a[i + 1])
j++;
if (j == n - 1)
flag = 0;
}
j = 0;
c++;
}
printf("%d", count);
}
总结
这个题目在官网上只属于简单题的类型,所以做会这一道后还是需要继续努力的。以后的时间都会在这上面分享自己对于真题的思路和代码。还是那句话,希望这个内容可以提供一些帮助。