1.编程求1*2*3*4*……*n的末尾有多少个0。
#include <stdio.h>
// 计算 n! 中末尾的0的个数
int count_zeros_in_factorial(int n) {
int count = 0;
for (int i = 5; n / i >= 1; i *= 5) {
count += n / i;
}
return count;
}
int main() {
int n;
printf("请输入一个整数 n:");
scanf("%d", &n);
int zeros_count = count_zeros_in_factorial(n);
printf("%d! 的末尾有 %d 个0\n", n, zeros_count);
return 0;
}
解释和步骤:
函数
count_zeros_in_factorial
: 这个函数用于计算 n! 中末尾的0的个数。通过一个循环,从 i=5 开始,每次乘以5,累加n / i
的值到count
中,直到n / i
的值小于1为止。这样就计算了所有能被 5,25,125,…整除的数的个数。主函数
main
: 在main
函数中,首先获取用户输入的整数n
,然后调用count_zeros_in_factorial
函数计算 n! 的末尾0的个数,并输出结果。
运行结果:
2.请输入一个50至100之间的整数n,求解n!。
#include <stdio.h>
#define MAX_DIGITS 500 // 定义最大位数为500,足以容纳100的阶乘
// 函数声明:计算大整数阶乘
void factorial(int n, int result[], int *result_size);
// 打印大整数数组
void printBigNumber(int result[], int result_size) {
for (int i = result_size - 1; i >= 0; i--) {
printf("%d", result[i]);
}
printf("\n");
}
// 计算大整数阶乘
void factorial(int n, int result[], int *result_size) {
result[0] = 1; // 初始结果为1
*result_size = 1; // 初始结果位数为1
// 计算 n!,从2开始乘到n
for (int i = 2; i <= n; i++) {
int carry = 0; // 进位
for (int j = 0; j < *result_size; j++) {
int product = result[j] * i + carry;
result[j] = product % 10; // 取个位数作为当前位
carry = product / 10; // 进位数
}
// 处理剩余的进位
while (carry > 0) {
result[*result_size] = carry % 10;
carry = carry / 10;
(*result_size)++;
}
}
}
int main() {
int n;
printf("请输入一个50至100之间的整数 n:");
scanf("%d", &n);
if (n < 50 || n > 100) {
printf("输入的整数不在50至100之间。\n");
return 1;
}
// 创建数组来存储结果
int result[MAX_DIGITS];
int result_size; // 存储结果的位数
// 计算阶乘
factorial(n, result, &result_size);
// 输出结果
printf("%d! = ", n);
printBigNumber(result, result_size);
return 0;
}
解释和步骤:
数组和常量定义:
MAX_DIGITS
定义了数组的最大长度,足够存储50至100之间任意整数的阶乘结果。函数
factorial
:
- 接受一个整数
n
和一个数组result
来存储阶乘的结果,以及一个指针result_size
来记录结果的位数。- 初始时,将结果设置为1,并且结果位数为1。
- 使用两层循环来模拟手工乘法的过程,每次将当前乘积的个位数存入数组中,并记录进位数。
- 每次乘完一轮,检查是否有剩余的进位需要处理,直到没有进位为止。
主函数
main
:
- 提示用户输入一个50至100之间的整数
n
。- 检查输入是否在有效范围内,如果不在范围内则输出错误信息并结束程序。
- 创建一个足够大的数组
result
来存储阶乘的结果。- 调用
factorial
函数计算阶乘,并将结果存储在result
数组中。- 调用
printBigNumber
函数打印计算出的阶乘结果。
运行结果:
3. 有A、B、C、D、E 5个人为某次竞赛的前五名,他们在名次公布前猜名次。
A说:B得第三名,C得第五名。
B说:D得第二名,E得第四名。
C说:B得第一名,E得第四名。
D说:C得第一名,B得第二名。
E说:D得第二名,A得第三名。
结果每个人都猜对了一半,实际名次是什么?
#include <stdio.h>
int main() {
int A, B, C, D, E; // A, B, C, D, E 分别代表ABCDE五人的名次
// 穷举ABCDE的排名,满足每个人猜对一半的条件
for (A = 1; A <= 5; ++A) {
for (B = 1; B <= 5; ++B) {
if (B == A) continue; // B不能和A同名次
for (C = 1; C <= 5; ++C) {
if (C == A || C == B) continue; // C不能和A或B同名次
for (D = 1; D <= 5; ++D) {
if (D == A || D == B || D == C) continue; // D不能和A、B或C同名次
for (E = 1; E <= 5; ++E) {
if (E == A || E == B || E == C || E == D) continue; // E不能和A、B、C或D同名次
// 检查每个人的猜测是否正确
int correct_count = 0;
if (B == 3 && C == 5) correct_count++; // A猜测
if (D == 2 && E == 4) correct_count++; // B猜测
if (B == 1 && E == 4) correct_count++; // C猜测
if (C == 1 && B == 2) correct_count++; // D猜测
if (D == 2 && A == 3) correct_count++; // E猜测
// 判断是否满足每个人猜对一半的条件
if (correct_count == 2) {
printf("实际名次为:A=%d, B=%d, C=%d, D=%d, E=%d\n", A, B, C, D, E);
return 0;
}
}
}
}
}
}
return 0;
}
解释和步骤:
穷举法:通过嵌套的循环遍历ABCDE五人可能的排名组合,从1到5,确保每个人的名次都不同。
条件检查:在每个排名组合中,检查每个人的猜测是否正确,根据题目提供的猜测条件进行判断。
正确答案判定:当找到满足每个人猜对一半条件的排名组合时,即输出实际名次。
运行结果:
4.百马百担问题:有100匹马,驮100担货。大马驮3担,中马驮2担,两匹小马驮1担,问大、中、小马各多少?
#include <stdio.h>
int main() {
int x, y, z; // x, y, z 分别表示大马、中马、小马的数量
// 穷举大马、中马、小马的数量,满足总数为100匹马,总载重为100担
for (x = 0; x <= 100; ++x) {
for (y = 0; y <= 100 - x; ++y) {
z = (100 - 3*x - 2*y) * 2; // 计算小马的数量
// 检查是否满足每种马的驮载条件
if (z >= 0 && z % 2 == 0&&x+y+z==100) {
printf("大马:%d 匹,中马:%d 匹,小马:%d 匹\n", x, y, z);
}
}
}
return 0;
}
解释和步骤:
穷举法:通过嵌套的循环遍历大、中、小马的数量可能组合,确保它们的总数为100匹马,同时总载重为100担货物。
条件检查:在每个马匹数量组合中,计算总载重是否为100担。如果满足条件,则输出对应的大马、中马、小马的数量。
输出结果:程序将打印所有满足条件的组合,即大、中、小马各自的数量,使得总数为100匹马,总载重为100担货物。
运行结果:
5. 输入整数N、K以及长度为N的无序序列,找到第K小数并输出。第一行输入N和K,第二行输入长度为N的整数数组。
#include <stdio.h>
// 交换函数,用于交换数组中两个元素的位置
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 分割函数,用于将数组按照基准数分成两部分,并返回基准数的位置
int partition(int arr[], int left, int right) {
int pivot = arr[right]; // 选择最右边的元素作为基准数
int i = left - 1; // i指向小于基准数的区域的最后一个元素
for (int j = left; j < right; ++j) {
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[right]); // 将基准数放到正确的位置上
return i + 1; // 返回基准数的位置
}
// 寻找第K小的数的函数
int findKthSmallest(int arr[], int left, int right, int k) {
if (k > 0 && k <= right - left + 1) {
int pivotIndex = partition(arr, left, right);
if (pivotIndex - left == k - 1)
return arr[pivotIndex];
if (pivotIndex - left > k - 1)
return findKthSmallest(arr, left, pivotIndex - 1, k);
return findKthSmallest(arr, pivotIndex + 1, right, k - (pivotIndex - left + 1));
}
return -1; // 如果k超出数组长度的范围,返回-1表示未找到
}
int main() {
int N, K;
printf("请输入整数 N 和 K:");
scanf("%d %d", &N, &K);
int arr[N];
printf("请输入长度为 N 的整数数组:");
for (int i = 0; i < N; ++i) {
scanf("%d", &arr[i]);
}
int result = findKthSmallest(arr, 0, N - 1, K);
if (result != -1)
printf("第 %d 小的数是:%d\n", K, result);
else
printf("输入的 K 超出数组长度的范围。\n");
return 0;
}
解释和步骤:
swap函数:用于交换数组中两个元素的位置。
partition函数:实现分割函数,选择最右边的元素作为基准数(pivot),将数组分成两部分,小于等于基准数的放在左边,大于基准数的放在右边,并返回基准数的位置。
findKthSmallest函数:递归地寻找第K小的数。在每次调用中,根据partition函数返回的基准数的位置,判断应该继续在左侧还是右侧进行搜索,直到找到第K小的数为止。
主函数main:
- 输入N和K。
- 输入长度为N的整数数组。
- 调用findKthSmallest函数找到第K小的数,并输出结果。
运行结果:
结语
最暗的夜
才会看见最美的星光
人生亦是如此
!!!