4.6 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 สูตรคูณแม่ N
น้องอนุบาลกำลังท่องสูตรคูณ ครูอยากได้แผ่นท่องของแม่ N ตั้งแต่ N คูณ 1 ไปจนถึง N คูณ M ให้พิมพ์สูตรคูณแม่ N ทีละบรรทัด
ข้อมูลเข้า
บรรทัดเดียว มีจำนวนเต็ม N และ M คั่นด้วยช่องว่าง โดยที่ 1 ≤ N ≤ 1000 และ 1 ≤ M ≤ 1000
ข้อมูลออก
M บรรทัด บรรทัดที่ i อยู่ในรูป N x i = ผลคูณ โดยมีช่องว่างหนึ่งช่องคั่นระหว่างทุกส่วนตามตัวอย่าง
7 57 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35ดูคำใบ้
ใช้ for ให้ตัวนับ i วิ่งจาก 1 ถึง M แต่ละรอบพิมพ์หนึ่งบรรทัด คือ N ตัวคูณ i และผลคูณ ระวังว่าต้องเป็น <= m ไม่ใช่ < m
ดูเฉลย
#include <stdio.h>
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
printf("%d x %d = %d\n", n, i, n * i);
}
return 0;
}ข้อ 2 คะแนนเฉลี่ยของห้อง
ห้องเรียนหนึ่งมีนักเรียน N คน สอบวิชาคณิตศาสตร์ได้คะแนนเต็ม 100 ครูอยากรู้คะแนนเฉลี่ยของห้อง และจำนวนนักเรียนที่สอบผ่าน ซึ่งคือคนที่ได้ตั้งแต่ 50 คะแนนขึ้นไป
ข้อมูลเข้า
บรรทัดแรกเป็นจำนวนเต็ม N (1 ≤ N ≤ 1000)
บรรทัดที่สองมีจำนวนเต็ม N ตัว คั่นด้วยช่องว่าง เป็นคะแนนของนักเรียนแต่ละคน แต่ละตัวอยู่ระหว่าง 0 ถึง 100
ข้อมูลออก
บรรทัดแรกพิมพ์คะแนนเฉลี่ย เป็นทศนิยม 2 ตำแหน่ง
บรรทัดที่สองพิมพ์จำนวนนักเรียนที่สอบผ่าน
4
55 70 49 8163.75
33
70 85 9081.67
3ดูคำใบ้
มีตัวแปรสองตัวที่ตั้งค่าเริ่มต้นเป็น 0 ก่อนเข้าลูป ตัวหนึ่งสะสมผลรวม อีกตัวนับคนที่ได้ตั้งแต่ 50 ขึ้นไป หลังลูปค่อยหาค่าเฉลี่ย อย่าลืมแปลงผลรวมเป็น double ก่อนหาร และพิมพ์ด้วย %.2f
ดูเฉลย
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int total = 0;
int passed = 0;
for (int i = 1; i <= n; i++) {
int score;
scanf("%d", &score);
total += score;
if (score >= 50) {
passed++;
}
}
printf("%.2f\n", (double)total / n);
printf("%d\n", passed);
return 0;
}ข้อ 3 วันที่ร้อนที่สุดและหนาวที่สุด
สถานีอากาศบนยอดดอยวัดอุณหภูมิทุกวันเป็นเวลา N วัน หน้าหนาวอุณหภูมิติดลบได้ ให้หาอุณหภูมิสูงสุดพร้อมบอกว่าเกิดขึ้นวันที่เท่าไร และอุณหภูมิต่ำสุดพร้อมบอกว่าเกิดขึ้นวันที่เท่าไร ถ้าค่าเดียวกันเกิดขึ้นหลายวัน ให้ตอบวันแรกที่เกิด วันแรกของการวัดคือวันที่ 1
ข้อมูลเข้า
บรรทัดแรกเป็นจำนวนเต็ม N (1 ≤ N ≤ 100000)
บรรทัดที่สองมีจำนวนเต็ม N ตัว คั่นด้วยช่องว่าง ตัวที่ i คืออุณหภูมิของวันที่ i แต่ละตัวอยู่ระหว่าง -50 ถึง 50
ข้อมูลออก
บรรทัดแรกพิมพ์อุณหภูมิสูงสุด เว้นวรรค แล้วตามด้วยวันที่เกิดครั้งแรก
บรรทัดที่สองพิมพ์อุณหภูมิต่ำสุด เว้นวรรค แล้วตามด้วยวันที่เกิดครั้งแรก
7
12 8 -2 15 15 3 -215 4
-2 3ดูคำใบ้
อ่านอุณหภูมิวันแรกก่อนเข้าลูป ให้เป็นทั้งค่ามากสุดและน้อยสุด และจำว่าเป็นวันที่ 1 แล้วค่อยวนวันที่ 2 ถึง N อย่าเริ่มค่ามากสุดที่ 0 เพราะอุณหภูมิติดลบได้ทุกวัน และถ้าเจอค่าเท่ากับค่ามากสุดเดิม ต้องไม่เปลี่ยนวัน จึงใช้ > ไม่ใช่ >=
ดูเฉลย
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int first;
scanf("%d", &first);
int highest = first, high_day = 1;
int lowest = first, low_day = 1;
for (int day = 2; day <= n; day++) {
int temp;
scanf("%d", &temp);
if (temp > highest) {
highest = temp;
high_day = day;
}
if (temp < lowest) {
lowest = temp;
low_day = day;
}
}
printf("%d %d\n", highest, high_day);
printf("%d %d\n", lowest, low_day);
return 0;
}ข้อ 4 บันไดดาว
ให้วาดบันไดสูง N ขั้นด้วยเครื่องหมาย * โดยชิดขวา แถวที่ 1 มีดาว 1 ดวง แถวที่ 2 มี 2 ดวง ไปจนถึงแถวที่ N มี N ดวง ดาวตัวขวาสุดของทุกแถวต้องอยู่คอลัมน์เดียวกัน ให้ใช้ช่องว่างนำหน้าเพื่อดันดาวไปทางขวา และห้ามมีช่องว่างหลังดาวตัวสุดท้ายของแถว
ข้อมูลเข้า
จำนวนเต็ม N หนึ่งตัว (1 ≤ N ≤ 100)
ข้อมูลออก
N บรรทัด เป็นรูปบันไดตามตัวอย่าง
4 *
**
***
****ดูคำใบ้
เขียนตารางก่อน แถวที่ i มีช่องว่างกี่ช่อง มีดาวกี่ดวง ลองกับ N = 4 แถวที่ 1 มีช่องว่าง 3 ดาว 1 แถวที่ 4 มีช่องว่าง 0 ดาว 4 แล้วแต่ละแถวใช้ลูปข้างในสองตัว ตัวแรกพิมพ์ช่องว่าง ตัวที่สองพิมพ์ดาว
ดูเฉลย
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int j = 1; j <= i; j++) {
printf("*");
}
printf("\n");
}
return 0;
}ข้อ 5 บัญชีค่าขนม
น้องจดบัญชีค่าขนมเป็นตัวเลขทีละรายการ ตัวเลขที่เป็นบวกคือเงินที่ได้รับ ตัวเลขที่ติดลบคือเงินที่จ่ายออกไป เมื่อจดครบแล้วน้องเขียน 0 ปิดท้ายไว้ ให้หาว่าได้รับเงินรวมเท่าไร จ่ายไปรวมเท่าไร และเหลือเงินสุทธิเท่าไร
ข้อมูลเข้า
จำนวนเต็มเรียงกันอยู่ในหนึ่งบรรทัดหรือหลายบรรทัด คั่นด้วยช่องว่างหรือการขึ้นบรรทัดใหม่ ตัวสุดท้ายคือ 0 ซึ่งบอกว่าจบข้อมูล และไม่ใช่รายการ ตัวเลขก่อนหน้า 0 มีไม่เกิน 1000 ตัว (อาจไม่มีเลยก็ได้) แต่ละตัวไม่ใช่ 0 และอยู่ระหว่าง -1000 ถึง 1000
ข้อมูลออก
สามบรรทัด บรรทัดแรกคือเงินที่ได้รับรวม บรรทัดที่สองคือเงินที่จ่ายรวม พิมพ์เป็นค่าบวก บรรทัดที่สามคือเงินรับรวมลบเงินจ่ายรวม ซึ่งติดลบได้
50 -20 -15 100 -40 0150
75
75ดูคำใบ้
ไม่รู้ว่ามีกี่รายการ จึงใช้ while (1) อ่านทีละตัว ถ้าเป็น 0 ให้ break ก่อนนำไปใช้ ถ้ามากกว่า 0 บวกเข้ารายรับ ถ้าน้อยกว่า 0 บวกเข้ารายจ่าย โดยเปลี่ยนเป็นค่าบวกก่อน เช่น spent -= amount ลองนึกด้วยว่าถ้าข้อมูลมีแค่ 0 ตัวเดียว ต้องพิมพ์อะไร
ดูเฉลย
#include <stdio.h>
int main()
{
int received = 0, spent = 0;
while (1) {
int amount;
scanf("%d", &amount);
if (amount == 0) {
break;
}
if (amount > 0) {
received += amount;
} else {
spent -= amount;
}
}
printf("%d\n", received);
printf("%d\n", spent);
printf("%d\n", received - spent);
return 0;
}ข้อ 6 ฝนตกติดกัน
สถานีวัดน้ำฝนจดปริมาณฝนของแต่ละวันเป็นมิลลิเมตร วันที่ฝนไม่ตกจดเป็น 0 สมุดจดกี่วันก็ได้ไม่แน่นอน ให้หาว่ามีกี่วันที่ฝนตก และฝนตกติดต่อกันนานที่สุดกี่วัน
ข้อมูลเข้า
ปริมาณฝนของแต่ละวันเรียงตามลำดับวัน เป็นจำนวนเต็มระหว่าง 0 ถึง 500 คั่นด้วยช่องว่างหรือการขึ้นบรรทัดใหม่ อ่านไปจนจบข้อมูลเข้า มีอย่างน้อย 1 วัน และไม่เกิน 100000 วัน
ข้อมูลออก
บรรทัดแรกพิมพ์จำนวนวันที่ฝนตก (ปริมาณฝนมากกว่า 0)
บรรทัดที่สองพิมพ์จำนวนวันที่ฝนตกติดต่อกันนานที่สุด ถ้าฝนไม่ตกเลยให้พิมพ์ 0
0 5 12 0 3 8 20 1 0 0 47
4ดูคำใบ้
ไม่รู้ว่ามีกี่วัน ให้อ่านด้วย while (scanf("%d", &rain) == 1) ใช้ตัวแปร streak นับว่าตอนนี้ฝนตกติดกันมากี่วันแล้ว วันที่ฝนตกเพิ่ม 1 วันที่ไม่ตกตั้งกลับเป็น 0 และเทียบกับค่ามากสุดทุกวันที่ฝนตก ไม่ใช่เฉพาะวันที่ช่วงฝนจบ ลองกับข้อมูลที่ฝนตกทุกวันดูว่าได้คำตอบถูกไหม
ดูเฉลย
#include <stdio.h>
int main()
{
int rain;
int rainy_days = 0, streak = 0, longest = 0;
while (scanf("%d", &rain) == 1) {
if (rain > 0) {
rainy_days++;
streak++;
if (streak > longest) {
longest = streak;
}
} else {
streak = 0;
}
}
printf("%d\n", rainy_days);
printf("%d\n", longest);
return 0;
}ข้อ 7 เลขนำโชค
หมอดูคนหนึ่งหาเลขนำโชคจากเลขทะเบียนรถ N ด้วยการบวกทุกหลักของ N เข้าด้วยกัน ถ้าผลยังมีตั้งแต่สองหลักขึ้นไปก็บวกทุกหลักของผลนั้นต่ออีก ทำไปเรื่อยๆ จนเหลือเลขหลักเดียว เช่น 9875 บวกทุกหลักได้ 29 บวกต่อได้ 11 บวกต่ออีกได้ 2 ซึ่งเป็นเลขหลักเดียว เลขนำโชคคือ 2
ให้พิมพ์ทุกเลขที่ได้ระหว่างทาง ตั้งแต่ N จนถึงเลขนำโชค
ข้อมูลเข้า
จำนวนเต็ม N หนึ่งตัว (0 ≤ N ≤ 1018)
ข้อมูลออก
บรรทัดเดียว เริ่มด้วย N แล้วตามด้วยเลขที่ได้จากการบวกหลักแต่ละครั้งตามลำดับ คั่นด้วยช่องว่างหนึ่งช่อง ถ้า N เป็นเลขหลักเดียวอยู่แล้ว ให้พิมพ์ N ตัวเดียว
98759875 29 11 277ดูคำใบ้
ลูปข้างนอกวนตราบที่เลขยังมีตั้งแต่สองหลักขึ้นไป (n >= 10) ลูปข้างในหาผลรวมของหลักด้วย % 10 กับ /= 10 แล้วให้ผลรวมกลายเป็น n ตัวใหม่ N ใหญ่ถึง 1018 ต้องใช้ long long และ %lld พิมพ์ N ตัวแรกก่อนเข้าลูป แล้วตัวถัดไปพิมพ์ช่องว่างนำหน้า
ดูเฉลย
#include <stdio.h>
int main()
{
long long n;
scanf("%lld", &n);
printf("%lld", n);
while (n >= 10) {
long long digit_sum = 0;
while (n > 0) {
digit_sum += n % 10;
n /= 10;
}
n = digit_sum;
printf(" %lld", n);
}
printf("\n");
return 0;
}ข้อ 8 เพชรกลวง
ให้วาดรูปเพชรกลวงขนาด N ด้วยเครื่องหมาย * รูปมีทั้งหมด 2N - 1 แถว แถวบนสุดและล่างสุดมีดาวดวงเดียว แถวกลางกว้างที่สุด ข้างในเพชรเป็นช่องว่าง มีดาวเฉพาะขอบ ดูรูปจากตัวอย่าง ห้ามมีช่องว่างหลังดาวตัวสุดท้ายของแต่ละแถว
ข้อมูลเข้า
จำนวนเต็ม N หนึ่งตัว (1 ≤ N ≤ 50)
ข้อมูลออก
2N - 1 บรรทัด เป็นรูปเพชรกลวงตามตัวอย่าง
4 *
* *
* *
* *
* *
* *
*ดูคำใบ้
แบ่งเป็นครึ่งบน N แถวกับครึ่งล่าง N - 1 แถว เขียนตารางของครึ่งบนก่อน แถวที่ i มีช่องว่างนำหน้า N - i ช่อง ตามด้วยดาว แล้วถ้า i มากกว่า 1 มีช่องว่างตรงกลาง 2i - 3 ช่องและดาวอีกดวง ครึ่งล่างคือครึ่งบนกลับหัวโดยไม่มีแถวที่ N ซ้ำ ลองให้ลูปวนแถว r จาก 1 ถึง 2N - 1 แล้วคำนวณว่าแถว r ตรงกับแถว i ไหนของครึ่งบน
ดูเฉลย
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int row = 1; row <= 2 * n - 1; row++) {
int i = row;
if (row > n) {
i = 2 * n - row;
}
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
printf("*");
if (i > 1) {
for (int j = 1; j <= 2 * i - 3; j++) {
printf(" ");
}
printf("*");
}
printf("\n");
}
return 0;
}ข้อ 9 ตัวหารของเลขใหญ่
ครูคณิตศาสตร์ให้เลข N มาหนึ่งตัว แล้วถามว่า N มีตัวหารที่เป็นจำนวนเต็มบวกกี่ตัว และตัวหารทั้งหมดรวมกันได้เท่าไร เช่น 12 มีตัวหาร 1 2 3 4 6 12 รวม 6 ตัว ผลรวมเท่ากับ 28 ข้อนี้ N ใหญ่มาก ต้องคิดเรื่องเวลาให้ดีก่อนเขียน
ข้อมูลเข้า
จำนวนเต็ม N หนึ่งตัว (1 ≤ N ≤ 1012)
ข้อมูลออก
บรรทัดเดียว มีจำนวนตัวหารของ N และผลรวมของตัวหารทั้งหมดของ N คั่นด้วยช่องว่าง
126 28369 91ดูคำใบ้
ลองหาร 1 ถึง N ต้องวนถึง 1012 รอบ ไม่ทันแน่นอน ตัวหารมาเป็นคู่ i กับ N / i และตัวที่เล็กกว่าในคู่ไม่เกิน √N จึงวนแค่ i * i <= n พอ เจอ i ที่หารลงตัวก็ได้ตัวหารสองตัวคือ i กับ N / i ยกเว้นตอนที่สองตัวนี้เท่ากัน ให้นับครั้งเดียว ผลรวมของตัวหารเกิน int ได้ ใช้ long long ทั้ง N ตัวนับ และผลรวม
ดูเฉลย
#include <stdio.h>
int main()
{
long long n;
scanf("%lld", &n);
long long count = 0, sum = 0;
for (long long i = 1; i * i <= n; i++) {
if (n % i == 0) {
long long pair = n / i;
count++;
sum += i;
if (pair != i) {
count++;
sum += pair;
}
}
}
printf("%lld %lld\n", count, sum);
return 0;
}ข้อ 10 นับจำนวนเฉพาะในช่วง
จำนวนเฉพาะคือจำนวนเต็มที่มากกว่า 1 และมีตัวหารที่เป็นจำนวนเต็มบวกแค่ 1 กับตัวมันเอง เช่น 2 3 5 7 11 ให้นับว่าตั้งแต่ A ถึง B (รวม A และ B) มีจำนวนเฉพาะทั้งหมดกี่ตัว
ข้อมูลเข้า
บรรทัดเดียว มีจำนวนเต็ม A และ B คั่นด้วยช่องว่าง (1 ≤ A ≤ B ≤ 106)
ข้อมูลออก
จำนวนของจำนวนเฉพาะที่อยู่ในช่วง A ถึง B
1 10410 204ดูคำใบ้
ใช้ลูปข้างนอกไล่ทุกเลข x จาก A ถึง B แล้วลูปข้างในตรวจว่า x เป็นจำนวนเฉพาะไหม ถ้าลูปข้างในลองหารถึง x - 1 จำนวนเฉพาะแต่ละตัวต้องวนเกือบ x รอบ ช่วง 1 ถึง 106 มีจำนวนเฉพาะเกือบแปดหมื่นตัว รวมแล้วหลายหมื่นล้านรอบ ให้ลองหารแค่ i * i <= x และ break ทันทีที่เจอตัวหาร อย่าลืมว่า 1 ไม่ใช่จำนวนเฉพาะ
ดูเฉลย
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
int count = 0;
for (int x = a; x <= b; x++) {
if (x < 2) {
continue;
}
int is_prime = 1;
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
is_prime = 0;
break;
}
}
if (is_prime) {
count++;
}
}
printf("%d\n", count);
return 0;
}