蓝桥杯练习试题及思路讲解
入门训练
0001 A+B 问题
问题描述
输入 A、B,输出 A+B。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入的第一行包括两个整数,由空格分隔,分别表示 A、B。
输出格式
输出一行,包括一个整数,表示 A+B 的值。
样例输入
12 45
样例输出
57
数据规模与约定
10000 <= A, B <= 10000。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d", a + b);
return 0;
}
0002 序列求和
问题描述
求1+2+3+...+n的值。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入包括一个整数n。
输出格式
输出一行,包括一个整数,表示1+2+3+...+n的值。
样例输入
4
样例输出
10
样例输入
100
数据规模与约定
1 <= n <= 1,000,000,000
提示
循环累加的方法是最直接的,然而,当数据规模很大时,这种“暴力”的方法往往会导致超时。如果使用 1000000000 作为你的程序的输入,你的程序是不是能在规定的上面规定的时限内运行出来。此时你可以使用求和公式,n = (1 + n) * n / 2。
本题另一个要值得注意的地方是答案的大小不在你的语言默认的整型 (int) 范围内,如果使用整型来保存结果,会导致结果错误。如果你使用 C++ 或 C 语言而且准备使用 printf 输出结果,则你的格式字符串应该写成 %I64d 以输出 long long 类型的整数。
本题的C源代码如下:
#include <stdio.h>
int main()
{
long long int n = 0;
scanf("%d", &n);
n = (1 + n) * n / 2;
printf("%I64d\n", n);
return 0;
}
0003 圆的面积
问题描述
给定圆的半径r,求圆的面积。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入包含一个整数r,表示圆的半径。
输出格式
输出一行,包含一个实数,四舍五入保留小数点后7位,表示圆的面积。
样例输入
4
样例输出
50.2654825
数据规模与约定
1 <= r <= 10000
提示
本题对精度要求较高,请注意π的值应该取较精确的值。你可以使用常量来表示 π,比如PI=3.14159265358979323,也可以使用数学公式来求 π,比如 PI=atan(1.0)*4 。
本题的C源代码如下:
#include <stdio.h>
#define PI 3.1415926535897932384626
int main()
{
int r = 0;
scanf("%d", &r);
double area = 0;
area = r * r * PI;
printf("%.7lf\n", area);
return 0;
}
0004 Fibonacci 数列
问题描述
Fibonacci 数列的递推公式为:Fn=Fn-1+Fn-2,其中 F1=F2=1。
当 n 比较大时,Fn 也非常大,现在我们想知道,Fn 除以 10007 的余数是多少。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入包含一个整数n。
输出格式
输出一行,包含一个整数,表示Fn除以10007的余数。
样例输入
10
样例输出
55
样例输入
22
样例输出
7704
数据规模与约定
1 <= n <= 1,000,000。
提示
在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
本题的C源代码如下:
思路:使用三个变量,每次循环根据前两个变量得到第三个的值,然后将第二、三个变量的值分别赋值给第一个和第二个,然后再根据前两个变量得到第三个的值,如此往复。
#include <stdio.h>
int main()
{
int m = 1, n = 1, x = 0, input = 0; // m , n 代表前俩数,x 代表当前数
scanf("%d", &input);
if (input == 1 || input == 2)
{
x = 1;
printf("%d\n", x);
}
else
{
for (input; input > 2; input--)
{
x = (m + n) % 10007;
m = n;
n = x;
}
printf("%d\n", x);
}
return 0;
}
递归法输出斐波那契数列任意一位:
#include <stdio.h>
int getFib(int i)
{
if (i == 1 || i == 2)
return 1;
else
return getFib(i - 1) + getFib(i - 2);
}
int main()
{
int i;
scanf("%d", &i);
printf("%d", getFib(i));
return 0;
}
输出斐波那契数列前 20 个数,每 5 个数换一行:
#include <stdio.h>
int main()
{
int m = 1, n = 1, x = 0;
int counter;
printf("%d %d ", m, n);
for (counter = 3; counter <= 50; counter++)
{
x = m + n;
if (counter % 5 == 0)
printf("%d\n", x);
else
printf("%d ", x);
m = n;
n = x;
}
return 0;
}
基础练习
0005 闰年判断
问题描述
给定一个年份,判断这一年是不是闰年。
当以下情况之一满足时,这一年是闰年:
1. 年份是4的倍数而不是100的倍数;
2. 年份是400的倍数。
其他的年份都不是闰年。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入包含一个整数y,表示当前的年份。
输出格式
输出一行,如果给定的年份是闰年,则输出 yes,否则输出 no。
样例输入
2013
样例输出
no
样例输入
2016
样例输出
yes
数据规模与约定
1990 <= y <= 2050。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int y = 0;
scanf("%d", &y);
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
printf("yes");
else
printf("no");
return 0;
}
0006 01字串
问题描述
对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:
00000
00001
00010
00011
00100
请按从小到大的顺序输出这32种01串。
时间限制:1.0s 内存限制:256.0MB
输入格式
本试题没有输入。
输出格式
输出32行,按从小到大的顺序每行一个长度为5的01串。
样例输出
00000
00001
00010
00011
<以下部分省略>
提示
评测系统不支持在 for 循环的循环条件中声明变量。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int a[5] = {0}, i = 0, k = 4;
for (i = 0; i < 32; i++)
{
int n = i, j = 0;
while (n != 0)
{
a[j++] = n % 2;
n /= 2;
}
for (k = 4; k >= 0; k--)
{
printf("%d", a[k]);
}
printf("\n");
}
return 0;
}
0007 字母图形
问题描述
利用字母可以组成一些美丽的图形,下面给出了一个例子:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。
输出格式
输出n行,每个m个字符,为你的图形。
样例输入
5 7
样例输出
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
数据规模与约定
1 <= n, m <= 26
提示
字母默认为 'A' ,字母所在位置的横坐标与纵坐标之差的绝对值与 'A' 相加,得到该位置的字符。C 语言使用函数 abs() 计算绝对值,在使用该函数时需要引入头文件:
include <stdlib.h>
本题的C源代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x = 0, y = 0, i = 0, j = 0;
scanf("%d %d", &x, &y);
char arr[x][y], str = 'A';
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = str + abs(i - j);
}
}
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
printf("%c", arr[i][j]);
}
printf("\n");
}
return 0;
}
0008 数列特征
问题描述
给出n个数,找出这n个数的最大值,最小值,和。
时间限制:1.0s 内存限制:256.0MB
输入格式
第一行为整数n,表示数的个数。
第二行有n个数,为给定的n个数,每个数的绝对值都小于10000。
输出格式
输出三行,每行一个整数。第一行表示这些数中的最大值,第二行表示这些数中的最小值,第三行表示这些数的和。
样例输入
5
1 3 -2 4 5
样例输出
5
-2
11
数据规模与约定
1 <= n <= 10000。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int i, j, max, min, sum = 0;
scanf("%d", &j);
int num[j];
for (i = 0; i < j; i++)
{
scanf("%d", &num[i]);
sum += num[i];
}
max = min = num[0];
for (i = 0; i < j; i++)
{
if (num[i] > max)
max = num[i];
if (num[i] < min)
min = num[i];
}
printf("%d\n%d\n%d\n", max, min, sum);
return 0;
}
0009 查找整数
问题描述
给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。
时间限制:1.0s 内存限制:256.0MB
输入格式
第一行包含一个整数n。
第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000。
第三行包含一个整数a,为待查找的数。
输出格式
如果a在数列中出现了,输出它第一次出现的位置(位置从1开始编号),否则输出-1。
样例输入
6
1 9 4 8 3 9
9
样例输出
2
数据规模与约定
1 <= n <= 1000。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int m, n, i, j = -1;
scanf("%d", &m);
int num[m];
for (i = 0; i < m; i++)
{
scanf("%d", &num[i]);
}
scanf("%d", &n);
for (i = 0; i < m; i++)
{
if (num[i] == n)
{
j = i + 1;
break;
}
}
printf("%d", j);
return 0;
}
0010 杨辉三角形
问题描述
杨辉三角形又称 Pascal 三角形,它的第 i+1 行是 $ (a+b)^i$ 的展开式的系数。
它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。
下面给出了杨辉三角形的前 17 行:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1
......
给出n,输出它的前n行。
时间限制:1.0s 内存限制:256.0MB
输入格式
输入包含一个数n。
输出格式
输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。
样例输入
4
样例输出
1
1 1
1 2 1
1 3 3 1
数据规模与约定
1 <= n <= 34
提示
每个杨辉三角数用 $num[x,y]$ 的形式表示,num 表示数值,x,y 是这个数在二维数组中的横纵坐标。如下表:
1[0,0] | |||||
---|---|---|---|---|---|
1[1,0] | 1[1,1] | ||||
1[2,0] | 2[2,1] | 1[2,2] | |||
1[3,0] | 3[3,1] | 3[3,2] | 1[3,3] | ||
1[4,0] | 4[4,1] | 6[4,2] | 4[4,3] | 1[4,4] | |
1[5,0] | 5[5,1] | 10[5,2] | 10[5,3] | 5[5,4] | 1[5,5] |
1[6,0] | 5[6,1] | 10[6,2] | 10[6,3] | 5[6,4] | 1[6,5] |
当 y==0 或者 x==y 时,num = 1。当 x==y 时换行。
其他情况,num = num[x-1, y-1] + num[x-1, y] 。
本题的C源代码如下:
数组法:
#include <stdio.h>
int main()
{
int n = 0; // n 表示输出的层数
scanf("%d", &n); // 用户输入要输出的层数,将值传递给 n
int x = 0, y = 0, num[n][n]; // x, y 用于循环计数,二维数组 num 用于存储杨辉三角数。
for (x = 0; x < n; x++) // 控制 x y 坐标变化,计算杨辉三角数并存储进数组里
{
num[x][0] = 1;
for (y = 1; y < x; y++)
num[x][y] = num[x - 1][y - 1] + num[x - 1][y];
num[x][x] = 1;
}
for (x = 0; x < n; x++)
{
for (y = 0; y <= x; y++)
printf("%d ", num[x][y]);
printf("\n");
}
return 0;
}
以等腰三角形样式输出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int s = 1, h; // 数值和三角形层数
int i, j; // 循环计数
scanf("%d", &h); // 输入层数
printf("1\n"); // 输出第一个 1
for (i = 2; i <= h; s = 1, i++) // 行数 i 从 2 到层高
{
printf("1 "); // 第一个 1
for (j = 1; j <= i - 2; j++) // 列位置 j 绕过第一个直接开始循环
//printf("%d ", (s = (i - j) / j * s));
printf("%d ", (s = (i - j) * s / j));
printf("1\n"); // 最后一个 1,换行
}
getchar(); // 暂停等待
scanf("%d", &s);
return 0;
}
时间和空间最优算法:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
int s = 1, h; // 数值和高度
int i, j; // 循环计数
scanf("%d", &h); // 输入层数
printf("1\n"); // 输出第一个 1
for (i = 2; i <= h; s = 1, i++) // 行数 i 从 2 到层高
{
printf("1 "); // 第一个 1
for (j = 1; j <= i - 2; j++) // 列位置 j 绕过第一个直接开始循环
printf("%d ", (s = (i - j) * s / j));
printf("1\n"); // 最后一个 1,换行
}
getchar(); // 暂停等待
system("pause");
return 0;
}
0011 特殊的数字/水仙花数
问题描述
153 是一个非常特殊的数,它等于它的每位数字的立方和,即 153=1×1×1+5×5×5+3×3×3 。编程求所有满足这种条件的三位十进制数。
时间限制:1.0s 内存限制:256.0MB
输出格式
按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
提示
枚举+循环判断
本题的C源代码如下:
#include <stdio.h>
int main()
{
int i, j, k;
for (i = 1; i <= 9; i++)
{
for (j = 0; j <= 9; j++)
{
for (k = 0; k <= 9; k++)
{
if (i * i * i + j * j * j + k * k * k == i * 100 + j * 10 + k)
printf("%d\n", i * 100 + j * 10 + k);
}
}
}
return 0;
}
解法②:
#include <stdio.h>
int main()
{
int num, hd, td, sd;
for (num = 100; num < 1000; num++)
{
hd = num % 10;
td = (num - num / 100 * 100) / 10;
sd = num / 100;
if (hd * hd * hd + td * td * td + sd * sd * sd == num)
{
printf("%d\n", num);
}
}
return 0;
}
0012 回文数
问题描述
1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
时间限制:1.0s 内存限制:512.0MB
输出格式
按从小到大的顺序输出满足条件的四位十进制数。
提示
枚举加判断。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int g, s, b, q, num; // g s b q 取自 "个十百千" 拼音首字母
for (num = 1000; num < 10000; num++)
{
g = num % 10;
s = (num - num / 100 * 100) / 10;
b = num / 100 % 10;
q = num / 1000;
if (g == q && s == b)
{
printf("%d\n", num);
}
}
return 0;
}
0013 特殊回文数
问题描述
123321是一个非常特殊的数,它从左边读和从右边读是一样的。
输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
时间限制:1.0s 内存限制:512.0MB
输入格式
输入一行,包含一个正整数n。
输出格式
按从小到大的顺序输出满足条件的整数,每个整数占一行。
样例输入
52
样例输出
899998
989989
998899
数据规模和约定
1<=n<=54。
提示
枚举加判断。
本题的C源代码如下:
#include <stdio.h>
int main()
{
int g, s, b, q, w, sw, num, n; // g s b q 取自 "个、十、百、千、万、十万" 拼音首字母
scanf("%d", &n);
for (num = 10000; num < 999999; num++)
{
g = num % 10;
s = num / 10 % 10;
b = num / 100 % 10;
q = num / 1000 % 10;
w = num / 10000 % 10;
sw = num / 100000 % 10;
if (sw == 0 && g == w && s == q && g + s + b + q + w == n)
printf("%d\n", num);
else if (sw != 0 && sw == g && s == w && b == q && g + s + b + q + w + sw == n)
printf("%d\n", num);
}
return 0;
}
0014 十进制转十六进制
问题描述
十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。
给出一个非负整数,将它表示成十六进制的形式。
时间限制:1.0s 内存限制:512.0MB
输入格式
输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647
输出格式
输出这个整数的16进制表示
样例输入
30
样例输出
1E
提示
按除 16 倒取余数(也可使用格式输出)。
十六进制格式化输出使用 %x
本题的C源代码如下:
倒取余数,这里建议使用 do while 循环,因为当 num = 0 时程序也必须执行一次以输出 0。
#include <stdio.h>
int main()
{
int num = 0, hex = 16, i = 0, arr[20];
scanf("%d", &num);
do
{
arr[i] = num % hex;
i++;
num /= hex;
} while (num);
for (i = i - 1; i >= 0; i--)
{
if (arr[i] < 10)
printf("%d", arr[i]);
else
printf("%c", arr[i] + 'A' - 10);
}
printf("\n");
return 0;
}
格式化输出:
#include <stdio.h>
int main()
{
int num = 0, hex = 16, i = 0, arr[20];
scanf("%d", &num);
printf("%x\n",&num);
return 0;
}
0015 十六进制转十进制
问题描述
从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。
时间限制:1.0s 内存限制:512.0MB
样例输入
FFFF
样例输出
65535
提示
按16进制展开。
按数位依次操作,每次将前面的乘16,再加上当前数位的值。
本题的C源代码如下:
#include <stdio.h>
int power(int p, int num);
int main()
{
char num[8] = "xxxxxxxx"; // 存储输入的数组
gets(num);
int i = 0, n = 0, p = 0; // i 循环计数,n 累计每一位的数值,p 每一位的次方
for (i = 8; i >= 0; i--)
{
if (num[i] != 120 && num[i] != 0)
{
n += power(p, num[i]);
p++;
}
}
printf("%d\n", n);
return 0;
}
int power(int p, int num)
{
int i = 0;
if (num >= '0' && num <= '9') // 如果是 1-9 ,就使值等于 1-9
{
num -= '0';
}
else if (num >= 'A' && num <= 'F') // 如果是 A-F ,就使值等于 10-15
{
num = num - 'A' + 10;
}
for (i = 0; i < p; i++) // 幂运算
{
num = num * 16;
}
return num;
}
0016 十六进制转八进制
问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
时间限制:1.0s 内存限制:512.0MB
输入格式
输入的第一行为一个正整数 n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
提示
先将十六进制数转换成二进制数,再由二进制数转换成八进制。
本题的C源代码如下:
0017 数列排序
问题描述
给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
时间限制:1.0s 内存限制:512.0MB
输入格式
第一行为一个整数n。
第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式
输出一行,按从小到大的顺序输出排序后的数列。
样例输入
5
8 3 6 4 9
样例输出
3 4 6 8 9
本题的C源代码如下:
#include <stdio.h>
int main()
{
int n = 0, i, j, temp;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
j = n;
for (j; j > 0; j--)
{
for (i = 0; i < j; i++)
{
if (a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
for (i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
return 0;
}