fmod函数
要对浮点数进行类似取模的操作,你可以使用math.h
库中的fmod
函数,它专门用于浮点数的取模运算。
代码如下:
#include <math.h>
m = ceil(fmod(t, 60));
这样,fmod(t, 60)
会返回t
除以60
后的余数,然后再用ceil
函数取整。
要对浮点数进行类似取模的操作,你可以使用math.h
库中的fmod
函数,它专门用于浮点数的取模运算。
代码如下:
#include <math.h>
m = ceil(fmod(t, 60));
这样,fmod(t, 60)
会返回t
除以60
后的余数,然后再用ceil
函数取整。
#include <stdlib.h>
是 C 标准库的一个头文件,它包含了许多与内存分配、进程控制、随机数生成、排序/搜索以及数据类型转换等相关的函数声明。这个头文件在 C 和 C++ 中都被广泛使用。
以下是 stdlib.h
中一些常用的函数和它们的用途:
malloc()
:分配一块未初始化的内存。
void* malloc(size_t size);
例如:
int* arr = (int*) malloc(10 * sizeof(int));
calloc()
:分配一块内存并将其初始化为零。
void* calloc(size_t num, size_t size);
例如:
int* arr = (int*) calloc(10, sizeof(int));
realloc()
:重新调整已分配的内存块的大小。
void* realloc(void* ptr, size_t new_size);
例如:
arr = (int*) realloc(arr, 20 * sizeof(int));
free()
:释放动态分配的内存。
void free(void* ptr);
例如:
free(arr);
rand()
:生成一个介于 0
和 RAND_MAX
之间的随机整数。
int rand(void);
例如:
int random_value = rand();
srand()
:设置随机数生成器的种子,常用于生成不同的随机数序列。
void srand(unsigned int seed);
例如:
srand(time(NULL)); // 使用当前时间作为种子
exit()
:终止程序执行,并返回一个状态码。
void exit(int status);
例如:
exit(0); // 正常退出
system()
:执行系统命令。
int system(const char* command);
例如:
system("ls"); // 在Linux系统中列出目录内容
atoi()
:将字符串转换为整数。
int atoi(const char* str);
例如:
int num = atoi("123");
atof()
:将字符串转换为浮点数。
double atof(const char* str);
例如:
double num = atof("123.45");
atol()
:将字符串转换为长整数。
long atol(const char* str);
strtol()
、strtod()
:这些函数提供了更灵活的字符串到数值转换方式,可以指定进制或错误处理。
long int strtol(const char* str, char** endptr, int base);
qsort()
:使用快速排序算法对数组进行排序。
void qsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*));
例如,排序一个整型数组:
int compare(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}
qsort(arr, n, sizeof(int), compare);
bsearch()
:使用二分查找在已排序的数组中查找元素。
void* bsearch(const void* key, const void* base, size_t num, size_t size, int (*compar)(const void*, const void*));
getenv()
:获取环境变量的值。
char* getenv(const char* name);
例如:
char* path = getenv("PATH");
#include <stdlib.h>
头文件提供了 C 程序中许多基础功能,包括:
malloc
、calloc
、realloc
、free
)rand
、srand
)exit
、system
)atoi
、atof
、strtol
)qsort
、bsearch
)它是一个通用的、实用的库,几乎在每一个 C 程序中都能找到它的使用场景。
#include<bits/stdc++.h>
是一个在 C++ 编程中经常使用的头文件,它包含了 C++ 标准库中几乎所有的头文件。因此,它在很多竞赛编程或者快速原型开发中被广泛使用,因为它可以避免手动包含每一个单独需要的库文件。
不过,需要注意以下几点:
#include<bits/stdc++.h>
这个文件并不是 C++ 标准的一部分,它是 GCC(GNU Compiler Collection)编译器的一部分,因此它可能在其他编译器上不可用。例如,Visual Studio 编译器就不支持这个头文件。所以,#include<bits/stdc++.h>
虽然非常方便,尤其是在竞赛编程中,但并不是一个“万能库”,也不是推荐在所有情况下使用的库。
在 C 语言中,动态数组指的是在程序运行时动态分配的数组,其大小不需要在编译时确定。我们通过动态内存分配函数(如 malloc
、calloc
和 realloc
)来实现动态数组。
malloc
分配动态数组:malloc
函数可以分配指定大小的内存。它返回一个 void*
类型的指针,需要强制转换为适当的指针类型。
语法:
void* malloc(size_t size);
例如,创建一个动态分配的整型数组:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n; // 数组的大小
printf("Enter the number of elements: ");
scanf("%d", &n);
// 动态分配一个包含 n 个整数的数组
int* array = (int*) malloc(n * sizeof(int));
// 检查内存分配是否成功
if (array == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// 使用数组
for (int i = 0; i < n; i++) {
array[i] = i + 1; // 示例填充数组
}
// 打印数组
for (int i = 0; i < n; i++) {
printf("%d ", array[i]);
}
printf("\n");
// 释放内存
free(array);
return 0;
}
malloc
分配 n * sizeof(int)
个字节,用于存储 n
个整数。malloc
返回 NULL
,程序可以通过这个指针检查分配是否成功。free()
来释放分配的内存。calloc
分配动态数组:calloc
是另一种动态内存分配函数,它会将分配的内存初始化为零。
语法:
void* calloc(size_t num, size_t size);
例如:
int* array = (int*) calloc(n, sizeof(int));
calloc
与 malloc
的主要区别是,calloc
分配的内存会被初始化为零,而 malloc
分配的内存是未初始化的。
realloc
调整动态数组大小:
如果你需要调整动态数组的大小,可以使用 realloc
函数。它会重新分配内存,保留原有的数据内容。
语法:
void* realloc(void* ptr, size_t new_size);
例如:
array = (int*) realloc(array, new_size * sizeof(int));
realloc
接收一个指向之前分配内存的指针 ptr
和新的大小 new_size
。realloc
返回 NULL
,原来的内存块依然有效。realloc
调整数组大小#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 5;
int* array = (int*) malloc(n * sizeof(int));
// 填充数组
for (int i = 0; i < n; i++) {
array[i] = i + 1;
}
printf("Original array: ");
for (int i = 0; i < n; i++) {
printf("%d ", array[i]);
}
printf("\n");
// 调整数组大小
int new_size = 10;
array = (int*) realloc(array, new_size * sizeof(int));
// 为新数组的元素赋值
for (int i = n; i < new_size; i++) {
array[i] = i + 1;
}
printf("Resized array: ");
for (int i = 0; i < new_size; i++) {
printf("%d ", array[i]);
}
printf("\n");
// 释放内存
free(array);
return 0;
}
malloc
或 calloc
来分配动态数组,使用 realloc
来调整数组大小。free()
来释放内存。在 C++17 及之后的版本中,标准库中引入了一个内置的 gcd
函数,用于计算两个整数的最大公约数(GCD)。它位于 <numeric>
头文件中,并使用欧几里得算法来高效地计算 GCD。
该函数位于 std
命名空间下,函数签名如下:
template <class T>
T gcd(T a, T b);
int
、long
、long long
等。#include <iostream>
#include <numeric> // 包含 gcd 函数
#include <vector>
int main() {
int a = 56;
int b = 98;
// 使用 C++17 的内置 gcd 函数
int result = std::gcd(a, b);
std::cout << "GCD of " << a << " and " << b << " is " << result << std::endl;
return 0;
}
GCD of 56 and 98 is 14
std::gcd
函数使用的是经过优化的欧几里得算法,能够高效地计算两个整数的最大公约数。std::gcd
来计算各种整数类型的 GCD,包括 int
、long
、long long
,甚至自定义类型,只要它们遵循整数类型的基本规则。你可以利用 std::gcd
来计算多个数的 GCD。假设我们想要计算一个数组中所有元素的 GCD,可以像这样结合 std::gcd
和 std::accumulate
:
#include <iostream>
#include <numeric> // 包含 gcd 和 accumulate 函数
#include <vector>
int main() {
std::vector<int> nums = {56, 98, 42};
// 使用 accumulate 来计算多个数的 GCD
int result = std::accumulate(nums.begin(), nums.end(), nums[0], std::gcd<int, int>);
std::cout << "GCD of the array is " << result << std::endl;
return 0;
}
GCD of the array is 14
在标准的 C 语言库中(如 stdio.h
或 stdlib.h
),没有内置的 gcd
函数。因此,如果需要在 C 语言中计算两个整数的最大公约数(GCD),你需要自己编写该函数。
long long gcd(long long a,long long b)
{
while(a != b)
{
if(a > b)
{
a = a - b;
}
else
{
b = b - a;
}
}
return a; // 返回a或b,因为最后它们相等并且是GCD
}
在每次循环中通过减法逐步接近两个数的最大公约数,源于“更相减损术”的原理。这种方法可以追溯到古代的数学家欧几里得,并且可以用来证明两个数的最大公约数在减法中逐渐逼近。
这段代码的目的是计算两个数 a
和 b
的最大公约数(GCD,Greatest Common Divisor)以下是对代码的解释:
while
循环执行的是一种较原始的 GCD 计算方法,称为“减法法”。它通过逐步减少两个数的值直到它们相等。
aa
和 bb
的大小。如果 aa
大于 bb
,就用 aa - bb
更新 aa
,否则用 bb - aa
更新 bb
。最终,aa
和 bb
会变成相等的数,而这个数就是它们的最大公约数。假设我们有两个数 a
和 b
,且 a > b
。在减法法中,我们每次用较大的数减去较小的数,直到两个数相等。以下是这种方法的核心思想:
保持最大公约数不变:
d
是 a
和 b
的最大公约数,即 d = gcd(a, b)
,这意味着 a
和 b
都可以被 d
整除(即 a = d * m
,b = d * n
,其中 m
和 n
是整数)。a
减去较小的数 b
后,得到的新数 a' = a - b
。a' = a - b
仍然可以被 d
整除,因为:a'
也是 d
的倍数,仍然与 b
有相同的最大公约数。收敛到最大公约数:
(a', b)
或 (a, b')
的差值越来越小。最终,两个数会变得相等,而这个相等的数就是 a
和 b
的最大公约数。aa = bb
)就是它们的最大公约数。假设 a = 24
,b = 18
,我们通过每次减法逐步计算最大公约数:
a = 24
, b = 18
,因为 a > b
,所以 a = a - b = 24 - 18 = 6
。a = 6
, b = 18
,因为 b > a
,所以 b = b - a = 18 - 6 = 12
。a = 6
, b = 12
,因为 b > a
,所以 b = b - a = 12 - 6 = 6
。a = b = 6
,所以最大公约数是 6。每一步中,最大公约数一直保持不变,直到最后两个数相等为止,而这个相等的数就是最大公约数。
实际计算 GCD 可以使用 欧几里得算法,它比这种减法法更高效。改进后的代码如下:
long long gcd(long long a,long long b)
{
if(b == 0)
return a;
return gcd(b, a % b); // 欧几里得算法
}
除了递归,你也可以用迭代的方式实现:
#include <iostream>
long long gcd(long long a, long long b) {
while (b != 0) {
long long temp = b;
b = a % b;
a = temp;
}
return a;
}
a % b
计算出 a
除以 b
的余数,接着交换 a
和 b
的值,继续计算,直到 b
为 0。这个实现方法比使用减法的方式更高效,尤其对于较大的数。
欧几里得算法(Euclidean algorithm)是一个用于计算两个整数的最大公约数(GCD,Greatest Common Divisor)的经典算法。它的基本原理是基于一个非常重要的数学定理:
若 d
是 a
和 b
的最大公约数,则 d
也是 b
和 a % b
的最大公约数。
设 a
和 b
是两个整数,且 a > b
,则可以写成如下的关系:
a = b * q + r
其中:
q
是商(整数),r
是余数,即 r = a % b
。根据这个关系式,可以重写为:
r = a - b * q
现在,让我们从 d = gcd(a, b)
出发进行推导,假设 d
是 a
和 b
的最大公约数。根据最大公约数的定义:
d
可以整除 a
,即 a = d * m
,其中 m
是某个整数。d
也可以整除 b
,即 b = d * n
,其中 n
是某个整数。接下来,我们要证明 d
也可以整除 r
(即 a % b
)。根据前面的等式:
r = a - b * q
代入 a = d * m
和 b = d * n
:
r = d m - (d n) * q
r = d (m - n q)
因此,r
是 d
的倍数,这说明 d
也整除 r
。
d
整除 b
,并且 d
也整除 r
,根据最大公约数的定义,d
是 b
和 r
的公约数。d = gcd(b, r)
,而 r = a % b
,这就证明了:这个过程可以重复,直到余数为 0。此时,剩下的数就是 a
和 b
的最大公约数。
a
和 b
,其中 a > b
。gcd(a, b)
等于 gcd(b, a % b)
。换句话说,较大的数 a
可以被较小的数 b
除尽,并且我们继续用 a
除以 b
的余数来替换 a
。b
和 a % b
作为新的一对数,直到其中一个数变为 0。欧几里得算法的核心思想是基于一个重要的数学定理,这个定理解释了为什么最大公约数(GCD)可以通过 a
和 b
转换为 b
和 a % b
来计算。下面是这个定理的详细解释。
a
替换为 a % b
,并不断计算余数,最终将问题缩小。d
可以同时整除 b
和 a % b
,因此 gcd(a, b)
可以递归地转换为 gcd(b, a % b)
。b
就是 a
和 b
的最大公约数。这个定理和算法的关键在于利用了“除法余数不影响公约数”的特性,使得我们可以通过递归或迭代高效地计算出最大公约数。
另:求最小公倍数的方法:
另两数相乘然后除以最大公约数。
tip:为了防止爆int可以先除,再乘。