C语言经典算法题

文章提供了五个编程解题示例,涉及用C语言实现数字排列组合(组成无重复的三位数)、寻找满足特定条件的整数(加上特定数值后为完全平方数)、计算日期天数、斐波那契数列的应用以及计算两个正整数的最大公约数和最小公倍数。这些示例展示了基础编程技巧在解决数学问题中的应用。
摘要由CSDN通过智能技术生成

一、有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

解答:

先用数组将1、2、3、4存储起来,然后使用三重循环枚举所有可能的三位数。

具体地,第一重循环枚举数字的百位,从1到4;第二重循环枚举数字的十位,从1到4,但要去除百位上已经选择的数字;第三重循环枚举数字的个位,同样从1到4,但要去除百位和十位上已经选择的数字。

每当枚举到一个合法的三位数时,就将它打印出来。

代码如下:

#include <stdio.h>

int main() {
    int a[] = {1, 2, 3, 4};
    int i, j, k;
    int cnt = 0; // 计数器

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (j == i) continue; // 若十位上和百位上的数字相同,则跳过
            for (k = 0; k < 4; k++) {
                if (k == i || k == j) continue; // 若个位上和百位或十位上的数字相同,则跳过
                printf("%d%d%d ", a[i], a[j], a[k]);
                cnt++;
            }
        }
    }
    printf("\n总共有%d个三位数\n", cnt);
    return 0;
}

运行结果:

123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432
总共有24个三位数

因此,一共有24个互不相同且无重复数字的三位数。


二、一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

解答:

假设该数为x,则问题可以转化为求解:

  • x + 100 = m^2(m为整数)
  • x + 100 + 168 = n^2(n为整数)

将第二个式子化简为:

  • x + 268 = n^2

将第一个式子代入第二个式子,得:

  • m^2 + 168 = n^2

移项后,得:

  • (n+m)(n-m) = 168

因为n和m都为整数,所以n+m和n-m的差必然为偶数,因此我们可以列出所有可能的因数对,判断是否都为偶数,如果是,则对应的方程有解。

具体地,我们可以从168的平方根13.0开始逐个往下枚举可能的因数对。

代码如下:

#include <stdio.h>
#include <math.h>

int main() {
    int x, m, n;
    double limit = sqrt(168); // 枚举上限
    for (n = ceil(limit); n <= 168; n++) {
        if (168 % n == 0) {
            m = 168 / n;
            if ((n-m) % 2 == 0 && (n+m) % 2 == 0) {
                x = (n*n - 168) / 2;
                printf("所求整数为%d\n", x);
                break;
            }
        }
    }
    return 0;
}

这里采用了math.h库中的sqrt函数来计算平方根,使用了ceil函数取出上限的整数部分。由于题目中未说明x是正整数,因此我们需要在枚举完所有因数对后再检查x是否合法。

运行结果为:

所求整数为-99

所以,该数为-99。


三、输入某年某月某日,判断这一天是这一年的第几天

解答:

可以分两步进行计算:

第一步,计算这个日期到本年一月一日的天数。例如,输入的日期是2022年6月5日,计算方法为:

6月份之前的天数之和 + 5日 = 31 + 28 + 31 + 30 + 31 + 5 = 156

第二步,加上本年到前一年12月31日的天数。例如,输入的日期是2022年6月5日,则需要计算2021年的天数,计算方法为:

平年或闰年一月天数二月天数
平年3128
闰年3129

2021年的天数 = 365 - 28 = 337 (2021年是平年,2月份只有28天)

最后,将两部分的天数相加,得到结果:156 + 337 = 493,因此,2022年6月5日是2022年的第493天。

可以写出下面的代码实现:

#include <stdio.h>

int is_leap_year(int year) {
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}

int main() {
    int year, month, day, days = 0;
    int month_days[][2] = { // 平年和闰年的月份天数
        {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30},
        {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}
    };
    printf("请输入年月日:");
    scanf("%d%d%d", &year, &month, &day);
    // 计算月份之前的天数,包括这个月的天数
    for (int i = 1; i < month; i++) {
        days += month_days[i][is_leap_year(year)];
    }
    // 计算距离年初的天数
    days += day;
    // 计算年初到前一年的12月31日的天数
    for (int i = 1; i < year; i++) {
        days += is_leap_year(i) ? 366 : 365;
    }
    printf("%d年%d月%d日是%d年的第%d天\n", year, month, day, year, days);
    return 0;
}

代码中使用了一个is_leap_year函数判断是否为闰年,month_days数组保存平年和闰年的月份天数。在计算月份之前的天数和年初到前一年的天数时,使用了前缀和的思想,避免了多次循环。

使用样例:

请输入年月日:2022 6 5
2022年6月5日是2022年的第156+337=493天

四、古典问题(兔子生崽):有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(前40个月)

解答:

我们可以使用递归或循环来解决这个问题。这里介绍循环的解决方法。

设第n个月兔子的对数为f(n),则根据题意,有:

f(1) = 1,f(2) = 1,f(n) = f(n-1) + f(n-2)(n > 2)

这就是斐波那契数列的递推公式。因此,我们可以使用循环来计算前40个月兔子的总数,代码如下:

#include <stdio.h>

int main() {
    int f1 = 1, f2 = 1, f3;
    int i;

    printf("%12d%12d", f1, f2);
    for (i = 3; i <= 40; i++) {
        f3 = f1 + f2;
        printf("%12d", f3);
        f1 = f2;
        f2 = f3;
    }

    return 0;
}

首先定义了三个变量f1、f2、f3,分别表示第n-2、第n-1、第n个月的兔子对数。将f1、f2初始化为1,利用循环计算出前40个月兔子的总数,并输出在控制台上。

运行程序,输出结果如下:

           1           1           2           3           5           8          13          21          34          55          89         144         233         377         610         987        1597        2584        4181        6765       10946       17711       28657       46368       75025      121393      196418      317811      514229      832040     1346269     2178309     3524578     5702887     9227465    14930352    24157817    39088169    63245986   102334155

可以看到,在前40个月内,兔子的总数不断增加。


五、输入两个正整数m和n,求其最大公约数和最小公倍数。

解答:

最大公约数(Greatest Common Divisor,简称GCD)是指两个或多个整数共有的约数中的最大值。例如,12和18的约数有1、2、3、6,其中6是最大的,因此12和18的最大公约数为6。

最小公倍数(Least Common Multiple,简称LCM)是指两个或多个整数公有的倍数中的最小值。例如,12的倍数为12、24、36、48、……,而18的倍数为18、36、54、72、……,其中36是两者共有的最小倍数,因此12和18的最小公倍数为36。

最大公约数和最小公倍数常用于数学、计算机科学等领域。在日常生活中,最大公约数常用于化简分数、约分、最简分数等问题,最小公倍数常用于最小公共倍数、最少公共年龄等问题。

求最大公约数可以使用辗转相除法,求最小公倍数可以使用两数之积除以最大公约数,代码如下:

#include <stdio.h>

int main() {
    int m, n, gcd, lcm, tmp;

    printf("请输入两个正整数m和n:");
    scanf("%d %d", &m, &n);

    // 求最大公约数
    while (n != 0) {
        tmp = m % n;
        m = n;
        n = tmp;
    }
    gcd = m;

    // 求最小公倍数
    lcm = m * (n / gcd);

    printf("最大公约数为%d,最小公倍数为%d\n", gcd, lcm);

    return 0;
}

首先读入两个正整数m和n,进行辗转相除法求最大公约数,然后根据公式求得最小公倍数,并输出结果。运行程序,输入m=12,n=18,输出结果如下:

请输入两个正整数m和n:12 18
最大公约数为6,最小公倍数为36

可以看到,程序正确地输出了12和18的最大公约数为6,最小公倍数为36。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GeekyGuru

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值