藍橋杯練習試題及思路講解
入門訓練
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);
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
", 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
", x);
}
else
{
for (input; input > 2; input--)
{
x = (m + n) % 10007;
m = n;
n = x;
}
printf("%d
", 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
", 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("
");
}
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("
");
}
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
%d
%d
", 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("
");
}
return 0;
}
以等腰三角形樣式輸出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int s = 1, h; // 數值和三角形層數
int i, j; // 迴圈計數
scanf("%d", &h); // 輸入層數
printf("1
"); // 輸出第一個 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
"); // 最後一個 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
"); // 輸出第一個 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
"); // 最後一個 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
", 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
", 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
", 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
", num);
else if (sw != 0 && sw == g && s == w && b == q && g + s + b + q + w + sw == n)
printf("%d
", 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("
");
return 0;
}
格式化輸出:
#include <stdio.h>
int main()
{
int num = 0, hex = 16, i = 0, arr[20];
scanf("%d", &num);
printf("%x
",&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);
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;
}