[0]zero-index clytie0x/zero-index

4.6 แบบฝึกหัด

เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น

ข้อ 1 สูตรคูณแม่ N

ระดับง่าย เวลาไม่เกิน 1 วินาที

น้องอนุบาลกำลังท่องสูตรคูณ ครูอยากได้แผ่นท่องของแม่ N ตั้งแต่ N คูณ 1 ไปจนถึง N คูณ M ให้พิมพ์สูตรคูณแม่ N ทีละบรรทัด

ข้อมูลเข้า

บรรทัดเดียว มีจำนวนเต็ม N และ M คั่นด้วยช่องว่าง โดยที่ 1 ≤ N ≤ 1000 และ 1 ≤ M ≤ 1000

ข้อมูลออก

M บรรทัด บรรทัดที่ i อยู่ในรูป N x i = ผลคูณ โดยมีช่องว่างหนึ่งช่องคั่นระหว่างทุกส่วนตามตัวอย่าง

7 5
7 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 คะแนนเฉลี่ยของห้อง

ระดับง่าย เวลาไม่เกิน 1 วินาที

ห้องเรียนหนึ่งมีนักเรียน N คน สอบวิชาคณิตศาสตร์ได้คะแนนเต็ม 100 ครูอยากรู้คะแนนเฉลี่ยของห้อง และจำนวนนักเรียนที่สอบผ่าน ซึ่งคือคนที่ได้ตั้งแต่ 50 คะแนนขึ้นไป

ข้อมูลเข้า

บรรทัดแรกเป็นจำนวนเต็ม N (1 ≤ N ≤ 1000)

บรรทัดที่สองมีจำนวนเต็ม N ตัว คั่นด้วยช่องว่าง เป็นคะแนนของนักเรียนแต่ละคน แต่ละตัวอยู่ระหว่าง 0 ถึง 100

ข้อมูลออก

บรรทัดแรกพิมพ์คะแนนเฉลี่ย เป็นทศนิยม 2 ตำแหน่ง

บรรทัดที่สองพิมพ์จำนวนนักเรียนที่สอบผ่าน

4
55 70 49 81
63.75
3
3
70 85 90
81.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 วันที่ร้อนที่สุดและหนาวที่สุด

ระดับง่าย เวลาไม่เกิน 1 วินาที

สถานีอากาศบนยอดดอยวัดอุณหภูมิทุกวันเป็นเวลา N วัน หน้าหนาวอุณหภูมิติดลบได้ ให้หาอุณหภูมิสูงสุดพร้อมบอกว่าเกิดขึ้นวันที่เท่าไร และอุณหภูมิต่ำสุดพร้อมบอกว่าเกิดขึ้นวันที่เท่าไร ถ้าค่าเดียวกันเกิดขึ้นหลายวัน ให้ตอบวันแรกที่เกิด วันแรกของการวัดคือวันที่ 1

ข้อมูลเข้า

บรรทัดแรกเป็นจำนวนเต็ม N (1 ≤ N ≤ 100000)

บรรทัดที่สองมีจำนวนเต็ม N ตัว คั่นด้วยช่องว่าง ตัวที่ i คืออุณหภูมิของวันที่ i แต่ละตัวอยู่ระหว่าง -50 ถึง 50

ข้อมูลออก

บรรทัดแรกพิมพ์อุณหภูมิสูงสุด เว้นวรรค แล้วตามด้วยวันที่เกิดครั้งแรก

บรรทัดที่สองพิมพ์อุณหภูมิต่ำสุด เว้นวรรค แล้วตามด้วยวันที่เกิดครั้งแรก

7
12 8 -2 15 15 3 -2
15 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 บันไดดาว

ระดับง่าย เวลาไม่เกิน 1 วินาที

ให้วาดบันไดสูง 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 บัญชีค่าขนม

ระดับง่าย เวลาไม่เกิน 1 วินาที

น้องจดบัญชีค่าขนมเป็นตัวเลขทีละรายการ ตัวเลขที่เป็นบวกคือเงินที่ได้รับ ตัวเลขที่ติดลบคือเงินที่จ่ายออกไป เมื่อจดครบแล้วน้องเขียน 0 ปิดท้ายไว้ ให้หาว่าได้รับเงินรวมเท่าไร จ่ายไปรวมเท่าไร และเหลือเงินสุทธิเท่าไร

ข้อมูลเข้า

จำนวนเต็มเรียงกันอยู่ในหนึ่งบรรทัดหรือหลายบรรทัด คั่นด้วยช่องว่างหรือการขึ้นบรรทัดใหม่ ตัวสุดท้ายคือ 0 ซึ่งบอกว่าจบข้อมูล และไม่ใช่รายการ ตัวเลขก่อนหน้า 0 มีไม่เกิน 1000 ตัว (อาจไม่มีเลยก็ได้) แต่ละตัวไม่ใช่ 0 และอยู่ระหว่าง -1000 ถึง 1000

ข้อมูลออก

สามบรรทัด บรรทัดแรกคือเงินที่ได้รับรวม บรรทัดที่สองคือเงินที่จ่ายรวม พิมพ์เป็นค่าบวก บรรทัดที่สามคือเงินรับรวมลบเงินจ่ายรวม ซึ่งติดลบได้

50 -20 -15 100 -40 0
150
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 ฝนตกติดกัน

ระดับกลาง เวลาไม่เกิน 1 วินาที

สถานีวัดน้ำฝนจดปริมาณฝนของแต่ละวันเป็นมิลลิเมตร วันที่ฝนไม่ตกจดเป็น 0 สมุดจดกี่วันก็ได้ไม่แน่นอน ให้หาว่ามีกี่วันที่ฝนตก และฝนตกติดต่อกันนานที่สุดกี่วัน

ข้อมูลเข้า

ปริมาณฝนของแต่ละวันเรียงตามลำดับวัน เป็นจำนวนเต็มระหว่าง 0 ถึง 500 คั่นด้วยช่องว่างหรือการขึ้นบรรทัดใหม่ อ่านไปจนจบข้อมูลเข้า มีอย่างน้อย 1 วัน และไม่เกิน 100000 วัน

ข้อมูลออก

บรรทัดแรกพิมพ์จำนวนวันที่ฝนตก (ปริมาณฝนมากกว่า 0)

บรรทัดที่สองพิมพ์จำนวนวันที่ฝนตกติดต่อกันนานที่สุด ถ้าฝนไม่ตกเลยให้พิมพ์ 0

0 5 12 0 3 8 20 1 0 0 4
7
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 เลขนำโชค

ระดับกลาง เวลาไม่เกิน 1 วินาที

หมอดูคนหนึ่งหาเลขนำโชคจากเลขทะเบียนรถ N ด้วยการบวกทุกหลักของ N เข้าด้วยกัน ถ้าผลยังมีตั้งแต่สองหลักขึ้นไปก็บวกทุกหลักของผลนั้นต่ออีก ทำไปเรื่อยๆ จนเหลือเลขหลักเดียว เช่น 9875 บวกทุกหลักได้ 29 บวกต่อได้ 11 บวกต่ออีกได้ 2 ซึ่งเป็นเลขหลักเดียว เลขนำโชคคือ 2

ให้พิมพ์ทุกเลขที่ได้ระหว่างทาง ตั้งแต่ N จนถึงเลขนำโชค

ข้อมูลเข้า

จำนวนเต็ม N หนึ่งตัว (0 ≤ N ≤ 1018)

ข้อมูลออก

บรรทัดเดียว เริ่มด้วย N แล้วตามด้วยเลขที่ได้จากการบวกหลักแต่ละครั้งตามลำดับ คั่นด้วยช่องว่างหนึ่งช่อง ถ้า N เป็นเลขหลักเดียวอยู่แล้ว ให้พิมพ์ N ตัวเดียว

9875
9875 29 11 2
7
7
ดูคำใบ้

ลูปข้างนอกวนตราบที่เลขยังมีตั้งแต่สองหลักขึ้นไป (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 เพชรกลวง

ระดับกลาง เวลาไม่เกิน 1 วินาที

ให้วาดรูปเพชรกลวงขนาด 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 ตัวหารของเลขใหญ่

ระดับยาก เวลาไม่เกิน 1 วินาที

ครูคณิตศาสตร์ให้เลข N มาหนึ่งตัว แล้วถามว่า N มีตัวหารที่เป็นจำนวนเต็มบวกกี่ตัว และตัวหารทั้งหมดรวมกันได้เท่าไร เช่น 12 มีตัวหาร 1 2 3 4 6 12 รวม 6 ตัว ผลรวมเท่ากับ 28 ข้อนี้ N ใหญ่มาก ต้องคิดเรื่องเวลาให้ดีก่อนเขียน

ข้อมูลเข้า

จำนวนเต็ม N หนึ่งตัว (1 ≤ N ≤ 1012)

ข้อมูลออก

บรรทัดเดียว มีจำนวนตัวหารของ N และผลรวมของตัวหารทั้งหมดของ N คั่นด้วยช่องว่าง

12
6 28
36
9 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 และมีตัวหารที่เป็นจำนวนเต็มบวกแค่ 1 กับตัวมันเอง เช่น 2 3 5 7 11 ให้นับว่าตั้งแต่ A ถึง B (รวม A และ B) มีจำนวนเฉพาะทั้งหมดกี่ตัว

ข้อมูลเข้า

บรรทัดเดียว มีจำนวนเต็ม A และ B คั่นด้วยช่องว่าง (1 ≤ A ≤ B ≤ 106)

ข้อมูลออก

จำนวนของจำนวนเฉพาะที่อยู่ในช่วง A ถึง B

1 10
4
10 20
4
ดูคำใบ้

ใช้ลูปข้างนอกไล่ทุกเลข 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;
}