Test Message

a149: 乘乘樂

內容

你拿到一個整數,卻忍不住想把每個位數都乘在一起。例如看到 356 就會想要知道 3 _ 5 _ 6 的值為何。快寫個程式幫幫為了乘數字而快發瘋的自己吧!


輸入

一開始有一個數字 T,表示共有幾組測試資料。
接下來有 T 個數字 n (0 <= n < 2147483648)。

3
356
123
9999

輸出

輸出可以拯救自己的結果。

90
6
6561


解題思路

簡單的字串處理。


完整程式碼

AC (2ms, 80KB)
#include<stdio.h>

int kase, sum;
char n[15];

int main()
{
scanf(" %d", &kase);
while (kase--)
{
scanf(" %s", n);
sum = 1;
for (int i = 0; n[i]; i++)
sum *= n[i] - '0';
printf("%d\n", sum);
}
return 0;
}

a148: You Cannot Pass?!

內容

你考了 n 科筆試題目,每科的滿分都是 100 分。老師說,如果平均大於 59 你就過關了。


輸入

輸入第一行為一個數字 n,接著有 n 個正整數。

1 60
3 0 80 75
5 61 61 61 61 55

輸出

若你被當了,請輸出「yes」,否則輸出「no」。

no
yes
no


解題思路

簡單的 for loop + if 判斷,唯一要注意的是當總平均為 59 分整的時候要輸出 “yes”


完整程式碼

AC (2ms, 80KB)
#include<stdio.h>

int n, m, sum;

int main()
{
while (scanf(" %d", &n) == 1)
{
sum = 0;
for (int i = 0; i < n; i++)
{
scanf(" %d", &m);
sum += m;
}
puts(sum > 59 * n ? "no" : "yes");
}
return 0;
}

a147: Print it all

內容

大於 0、整數、不可以被 7 整除、小於 n,請輸出所有可能的數字。


輸入

輸入為一個整數 n,其中 n 不大於 10000。
若 n = 0 表示資料結束。

5
10
20
0

輸出

輸出如前述,各個數字之間以一個空白隔開。

1 2 3 4
1 2 3 4 5 6 8 9
1 2 3 4 5 6 8 9 10 11 12 13 15 16 17 18 19


解題思路

簡單的 for loop + if 判斷。


完整程式碼

AC (4ms, 108KB)
#include <stdio.h>

int n;

int main()
{
while (scanf(" %d", &n) == 1 && n)
{
for (int i = 1; i < n; i++)
{
if (i % 7)
printf("%d ", i);
}
putchar('\n');
}
return 0;
}

a121: 質數又來囉

內容

你的好朋友質數先生又來找你囉,給你兩個數字,請算出這兩個數字包含的範圍內有幾個質數。


輸入

輸入兩個正整數 a,b(1<=a<=b<=100000000)。

保證 b-a<=1000

3 7
6 6
30 50

輸出

輸出一個非負整數,代表 a 到 b 之間(包含 a,b)總共有幾個質數。

3
0
5


解題思路

從開頭試除到結尾,由於任意數不包含自己之最大可能因數為該數的開根號,所以試除時利用該結論簡少不必要的判斷加速。


完整程式碼

AC (0.2s, 88KB)
#include <stdio.h>

int n, m;

int main()
{
while (scanf("%d %d", &n, &m) == 2)
{
int num = 0, i = n;
for (; i < 2 && i <= m; i++)
;
for (; i <= m; i++)
{
num++;
for (int j = 2; j * j <= i; j++)
{
if (i % j == 0)
{
num--;
break;
}
}
}
printf("%d\n", num);
}
return 0;
}

a104: 排序

內容

幫我排個數字謝謝 QQ


輸入

有多筆測資以 EOF 為結束

第一行有一個正整數 n(1<=n<=1000),代表有幾個數字要請你幫忙排

第二行有 n 個可以用 int 儲存的正整數

6
7 9 0 4 1 8
8
1 9 9 0 0 9 2 8

輸出

輸出 n 個已由小到大排序好的正整數

0 1 4 7 8 9
0 0 1 2 8 9 9 9


解題思路

插入排序法


完整程式碼

AC (4ms, 92KB)
#include <stdio.h>
#define SWAP(x, y) \
x = x ^ y, \
y = x ^ y, \
x = x ^ y

int n, list[1010];

int main()
{
while (scanf(" %d", &n) == 1)
{
scanf(" %d", &list[0]);
for (int i = 1; i < n; i++)
{
scanf(" %d", &list[i]);
for (int j = i; j && list[j] < list[j - 1]; j--)
SWAP(list[j], list[j - 1]);
}
for (int i = 0; i < n; i++)
printf("%d ", list[i]);
putchar('\n');
}
return 0;
}

a095: 麥哲倫的陰謀

內容

在禁忌的貝殼城裡存在著一座監獄

有 N 個犯人被關在裡頭

我們只知道 …..

“他們都帶著帽子”

這是一頂神奇的帽子

稱作 “廬山帽”

是貝殼城裡的特產

分為紅色及白色兩種

凡是帶上 “廬山帽” 的人 ……

就會 “不識廬山真面目” !!!!

而監獄內的所有犯人都被配帶了這一頂可怕的帽子 0.0

而邪惡的所長麥哲倫想到了一個邪惡又沒有良心的鬼計畫:

“ 猜帽子 “

只要能猜出自己的帽子顏色即可立即出獄

但猜錯者須以死謝罪

而你可以假設監獄裡的犯人都跟羅賓一樣絕頂聰明

不會有想要以死謝罪的白痴行為

因此

在 N 個犯人的監獄中,麥哲倫所長將 M 頂紅帽配給其中的犯人

請問最少需要幾天,監獄內的所有犯人均可以確定自己的帽子顏色後出獄

PS. 犯人並不知道共有幾頂紅帽,只知道紅帽至少有一頂,而且不可互相討論 = =


輸入

輸入兩數 N,M (1 < M <= N < 231

代表 N 個犯人,M 頂紅帽

10 1
10 2

輸出

輸出最少幾天所有犯人均可以確定自己的帽子顏色後出獄

2
3


解題思路

重點在紅帽的數量,白帽不會影響邏輯判斷

  1. 如果只有 1 頂,紅帽人看到其他人都是白帽,就能確定自己是紅帽,他就能確定自己是紅帽離開。
    第 2 天白帽人發現戴紅帽人走了,就能確定自己是白帽離開。

  2. 如果有 2 頂,紅帽人的只會看到 1 個人戴紅帽(另一個在他頭上)。
    第 2 天,紅帽人發現另一個戴紅帽的不走 = 有人也戴紅帽,但剩下的都是白帽人,所以自己頭上的一定是紅帽,兩個紅帽人的就能確定自己是紅帽離開。
    第 3 天,白帽人發現戴紅帽人走了,就能確定自己是白帽離開。

  3. 如果有 3 頂,紅帽人的就會看到 2 個人戴紅帽(最後一個在他頭上)。
    第 2 天,(不重要)
    第 3 天,這時候紅帽人會發現如果自己戴的是白帽,那看到的兩個紅帽人所看到的情況應該是”狀況 2”,但他們第 2 天都沒有離開,代表還有人戴紅帽,但剩下的都是白帽人,所以自己頭上的一定是紅帽,三個紅帽人的就能確定自己是紅帽離開。
    第 4 天,白帽人發現戴紅帽人走了,就能確定自己是白帽離開。

  4. 之後情況同理類推。

觀察上面的情況可以發現,紅帽人能確認自己是紅帽並離開的天數是他”看見”的紅帽數 + 1,白帽人能確認自己是白帽並離開的天數是他看見紅帽人離開的天數 + 1,而紅帽人”看見”的紅帽數 + 1 = 紅帽的總數(看不到自己頭上的),所以可以得到結論:

紅帽人離開天數 = 紅帽數
全部離開天數 = 白帽人離開天數 = 紅帽人離開天數 + 1 = 紅帽數 + 1

唯一要注意的是:如果紅帽數 = 總人數,就不會有白帽人,也就是紅帽人 = 總人數,這時候

全部離開天數 = 紅帽人離開天數 = 紅帽數


完整程式碼

AC (34ms, 100KB)
#include <stdio.h>

int n, m;

int main()
{
while (scanf(" %d %d", &n, &m) == 2)
{
printf("%d\n", n == m ? m : m + 1);
}
return 0;
}

a065: 提款卡密碼

內容

文文記性不太好,常常會忘東忘西。他也常忘記提款卡密碼,每次忘記密碼都得帶著身份證、存摺、印章親自到銀行去重設密碼,還得繳交 50 元的手續費,很是麻煩。後來他決定把密碼寫在提款卡上免得忘記,但是這樣一來,萬一提款卡掉了,存款就會被盜領。因此他決定以一個只有他看得懂的方式把密碼寫下來。

他的密碼有 6 位數,所以他寫下了 7 個大寫字母,相鄰的每兩個字母間的「距離」就依序代表密碼中的一位數。所謂「距離」指的是從較「小」的字母要數幾個字母才能數到較「大」字母。字母的大小則是依其順序而定,越後面的字母越「大」。

假設文文所寫的 7 個字母是 POKEMON,那麼密碼的第一位數就是字母 P 和 O 的「距離」,由於 P 就是 O 的下一個字母,因此,從 O 開始只要往下數一個字母就是 P 了,所以密碼的第一位數就是 1。密碼的第二位數則是字母 O 和 K 的「距離」,從 K 開始,往下數 4 個字母 (L, M, N, O) 就到了 O,所以第二位數是 4,以此類推。因此,POKEMON 所代表的密碼便是 146821。

噓!你千萬別把這個密秘告訴別人哦,要不然文文的存款就不保了。


輸入

輸入有若干筆測試資料,每筆一行,每行有 7 個相連的大寫英文字母。

POKEMON
TYPHOON

輸出

對於每筆測試資料,輸出它所代表的密碼。

146821
598701


解題思路

簡單的字元處理。


完整程式碼

AC (10ms, 84KB)
#include <stdio.h>

char str[10];

int main()
{
while (scanf(" %s", str) == 1)
{
for (int i = 0; i < 6; i++)
printf("%d", str[i] > str[i + 1] ? str[i] - str[i + 1] : str[i + 1] - str[i]);
putchar('\n');
}
return 0;
}

a059: 完全平方和

內容

給你一個範圍 a 到 b ,請你找出 a 與 b 之間所有完全平方數的和。

例如:範圍 [3, 25] 中所有完全平方數的和就是 4 + 9 + 16 + 25 = 54 。


輸入

輸入的第一列有一個整數 T (1≦T≦100),代表以下有多少組測試資料。

每組測試資料為兩列,包含兩個數 a 與 b (0≦a≦b≦1000)。

2
1
5
5
35

輸出

每組測試資料輸出一列,內容為 a 及 b 間所有完全平方數的和。

Case 1: 5
Case 2: 50


解題思路

建平方表,判斷時將符合條件的平方和加總即可。


完整程式碼

AC (2ms, 92KB)
#include <stdio.h>
#define MAX 32

int kase, f, t, sq[MAX];

int main()
{
for (int i = 0; i < MAX; i++)
sq[i] = i * i;
while (scanf(" %d", &kase) == 1)
{
for (int kas = 1; kas <= kase; kas++)
{
scanf(" %d %d", &f, &t);
int i = 0, sum = 0;
while (sq[i] < f)
i++;
do
{
sum += sq[i];
} while (++i < MAX && sq[i] <= t);
printf("Case %d: %d\n", kas, sum);
}
}
return 0;
}

a058: MOD3

內容

相信判斷一個數除以三的餘數是多少,對你來說應該沒有問題。那,如果一次請你判斷很多個數呢嘿嘿?給你 n 個數字,請你輸出 3k、3k+1、3k+2 的數各有幾個


輸入

第一行有一個正整數 n,代表接下來有幾個數字,
接著有 n 個介於 1 到 50000 之間的數字,請你做判斷

5
1
2
3
4
5

輸出

輸出三個數字(以空白隔開),
分別為 n 個數字中,三的倍數、三的倍數+1、三的倍數+2 的數量

1 2 2


解題思路

開一個陣列,之後每個輸入取餘完,餘 0 就丟第 0 項、餘 1 丟 1、餘 2 丟 2,最後依序輸出陣列 0~2 項。


完整程式碼

AC (2ms, 76KB)
#include <stdio.h>

int n , m;

int main()
{
while (scanf(" %d", &n) == 1)
{
int rem[3] = { 0 };
while (n--)
{
scanf(" %d", &m);
rem[m % 3]++;
}
printf("%d %d %d\n", rem[0], rem[1], rem[2]);
}
return 0;
}

a054: 電話客服中心

內容

很多銀行及公司設立了電話客服中心來服務他們的客戶。為了加速身份的查核,常常會要求打電話進來的客戶輸入他的身份證號碼。可是電話上只有數字鍵,要輸入身份證號碼的第一個字母有點麻煩,因此有的語音系統會要求來電者輸入後 9 碼,再根據後 9 碼來推算可能的英文字母。

很多人都知道,身份證號碼的最後一碼是「檢查碼」,它是用前 9 碼所推算出來的,其推算的規則如下:

先依照下表將英文字母轉換為 2 位數字,再加上第 2 到第 9 位的 8 位數字一共有 10 位數字。

台北市 A 10   彰化縣 N 22
台中市 B 11   新竹市 O 35
基隆市 C 12   雲林縣 P 23
台南市 D 13   嘉義縣 Q 24
高雄市 E 14   台南縣 R 25
台北縣 F 15   高雄縣 S 26
宜蘭縣 G 16   屏東縣 T 27
桃園縣 H 17   花蓮縣 U 28
嘉義市 I 34   台東縣 V 29
新竹縣 J 18   金門縣 W 32
苗栗縣 K 19   澎湖縣 X 30
台中縣 L 20   陽明山 Y 31
南投縣 M 21   連江縣 Z 33

由左至右,第一位乘 1,第二位乘 9,第三位乘 8,第四位乘 7…,以此類推,最後一位乘 1。
求各位相對數字乘積的總和 s。
求 s 的個位數 m。
檢查碼 c = 10 - m 。
假設某人的身份證號碼前 9 碼為 F13024567,那麼他的最後一位檢查碼的計算過程如下:

   F       1    3    0    2    4    5    6    7
 1    5    1    3    0    2    4    5    6    7
×1   ×9   ×8   ×7   ×6   ×5   ×4   ×3   ×2   ×1
-----------------------------------------------------
 1 + 45 +  8 + 21 +  0 + 10 + 16 + 15 + 12 +  7 = 135
 檢查碼 = 10 - (135 % 10) = 5

根據上面的規則,A12345678、M12345678 和 W12345678 這三個號碼的檢查碼都是 9。因此,如果在電話上所輸入的後 9 碼是 123456789 時,它的第一位英文字母可能是 A,也可能是 M 或 W。


輸入

輸入有若干筆測試資料,每筆一行,含有一個身份證號碼的後 9 碼。

130245675
123456789

輸出

對於每筆測試資料,將可能的第一位大寫字母依字母順序輸出於一行。

FS
AMW


解題思路

先把英文對應的數字處理用

n = n / 10 + n % 10

處理成身分證驗證用的檢查碼並見表

將第 1~9 位數字轉成檢查碼並加總,之後再分別加上 A~Z 的檢查碼並 %10 判斷是否整除,是就輸出。


完整程式碼

AC (2ms, 96KB)
#include <stdio.h>

int sum, eng[26] = { 10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,34 ,18 ,19 ,20 ,21
,22 ,35 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,32 ,30 ,31 ,33 };
char input[11];

int main()
{
for (int i = 0; i < 26; i++)
eng[i] = eng[i] / 10 + (eng[i] % 10) * 9;
while (scanf(" %s", input) == 1)
{
sum = (input[7] - '0') + (input[8] - '0');
for (int i = 0; i < 7; i++)
sum += (input[i] - '0') * (8 - i);
for (int i = 0; i < 26; i++)
{
if (!((sum + eng[i]) % 10))
putchar('A' + i);
}
putchar('\n');
}
return 0;
}