洛谷刷题记录
前言:明天打蓝桥杯,希望自己进决赛,我太菜了呜呜呜呜😞😞😞😞
万能头文件
#include<bits/stdc++.h>
多行字符串
- C++中的
printf
函数有一种功能,可以多行打印字符串:
#include<bits/stdc++.h>
using namespace std;
long long t,a,b,i;
int main()
{
printf(
" *\n"
" ***\n"
"*****\n"
" ***\n"
" *\n");
return 0;
}
- C++11 raw string literal 技术:C++11中引入了原始字符串字面值(raw string literal)技术,它允许将字符串字面值包含在两个R"delim()delim"之间的形式中,其中delim是一个自定义的分界符。与普通的字符串字面值不同,原始字符串字面值可以包含任意字符,包括换行符和双引号等特殊字符,而不需要使用转义序列。
#include<iostream>
int main()
{
std::cout<<R"( ********
************
####....#.
#..###.....##....
###.......###### ### ###
........... #...# #...#
##*####### #.#.# #.#.#
####*******###### #.#.# #.#.#
...#***.****.*###.... #...# #...#
....**********##..... ### ###
....**** *****....
#### ####
###### ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
########################################## #----------#
#.....#......##.....#......##.....#......# #----------#
########################################## #----------#
#.#..#....#..##.#..#....#..##.#..#....#..# #----------#
########################################## ############ )";
}
memset(a,0,sizeof(a))
memset(a, 0, sizeof(a))
是一个C/C++语言中常用的函数调用,在 C++ 标准库的<cstring>
头文件中定义,用于将指定内存块的值设置为特定的值。它通常用于将数组或其他内存区域的内容清零。- 参数解释如下:
-
a
:表示要清零的内存块的起始地址。0
:表示要设置的特定值,这里是0,即将内存块的每个字节都设置为0。sizeof(a)
:表示要清零的内存块的大小,单位是字节。sizeof(a)
返回的是变量a
所占用的内存空间大小。
- 综合起来,
memset(a, 0, sizeof(a))
的作用是将数组a
的每个字节都设置为0。这在初始化数组或者清空数组内容时非常常见。需要注意的是,memset
函数针对的是字节操作,所以对于非字符类型的数组,可能会导致字节与数据类型不匹配的问题。建议在使用memset
函数时,确保所操作的内存块是适当的数据类型。
大整数相乘
#include<bits/stdc++.h>
using namespace std;
int main(){
char sa[2001],sb[2001];
int a[2002],b[2002],c[4003];
cin>>sa>>sb;
a[0] = strlen(sa);
b[0] = strlen(sb);
for (int i = 1; i <= a[0]; ++i) {
a[i] = sa[a[0]-i] - '0';
}
for (int i = 1; i <= b[0]; ++i) {
b[i] = sb[b[0]-i] - '0';
}
for (int i = 1; i <= a[0]; ++i)
for (int j = 1; j <= b[0]; ++j) {
c[i+j-1] += a[i] * b[j];
}
for (int i = 1; i < a[0] + b[0]; ++i) {
if (c[i] > 9){
c[i+1] += c[i]/10;
c[i] = c[i]%10;
}
}
int len = a[0] + b[0];
while(c[len] == 0&&len > 1) //去除数字首多余的0的操作
len--;
for (int i = len; i >0 ; --i) {
cout<<c[i];
}
return 0;
}
reverse()
-
其格式是: (reverse( 数组名 .().begin() , 数组名 .().end() )😉;
-
reverse()
函数是 C++ 标准库中的<algorithm>
头文件中的函数。该头文件提供了许多常用的算法函数,包括排序、搜索、操作容器等#include<bits/stdc++.h>//万能头文件 using namespace std; string a; int main() { cin>>a; reverse(a.begin(),a.end()); cout<<a; }
erase()
-
是 C++ 标准库中的
std::string
类的成员函数,用于删除字符串中的字符或子串 -
-
删除单个字符(基于索引):
std::string str = "Hello, World!"; str.erase(5); // 删除索引为5的字符('W')
-
删除字符范围:
std::string str = "Hello, World!"; str.erase(5, 6); // 删除从索引5开始的6个字符('W'到'!')
-
清空整个字符串:
std::string str = "Hello, World!"; str.erase(); // 清空字符串
-
-
erase()
函数的第一个参数是开始删除的位置(索引),第二个参数(可选)是要删除的字符数量。如果只提供一个参数,它将删除从该位置开始直到字符串末尾的所有字符。如果提供了两个参数,它将删除指定范围内的字符。 -
请注意,
erase()
函数会直接修改原始字符串,而不是创建一个新的字符串。这使得它在需要原地修改字符串时非常有用。然而,这种方法在删除多个字符时效率较低,因为每次删除后,字符串的内部结构都会发生变化,这可能导致额外的开销。如果你需要频繁地删除字符,可能需要考虑其他数据结构,如std::vector<char>
或std::list<char>
,它们在插入和删除操作时通常更加高效。
insert()
-
insert()
是std::string
类的一个成员函数,用于在字符串的指定位置插入另一个字符串。这个函数非常灵活,可以插入单个字符、字符串或者字符数组。 -
std::string& insert (size_t pos, const char *s, size_t n); std::string& insert (size_t pos, const char *s); std::string& insert (size_t pos, size_t n, char c); template<class InputIterator> std::string& insert (size_t pos, InputIterator first, InputIterator last);
pos
:插入位置的索引。如果pos
超出字符串的有效范围,插入操作会在字符串的末尾执行。s
:要插入的字符串或字符数组。n
:要插入的字符数量。如果使用const char *s
和size_t n
的重载,n
指定了从s
中要插入的字符数量。如果使用单个字符的重载,n
被忽略。c
:要插入的单个字符。first
和last
:输入迭代器的范围,指定了要插入的元素序列。
ceil()
ceil()
函数是一个数学函数,用于向上取整。它返回不小于指定值的最小整数。在 C++ 中,ceil()
函数是由 C++ 标准库的<cmath>
头文件提供的。
floor()
ceil()
函数是一个数学函数,用于向下取整。它返回不小于指定值的最小整数。在 C++ 中,ceil()
函数是由 C++ 标准库的<cmath>
头文件提供的。
sort()不稳定排序
sort()
函数是一个快速排序算法的实现,用于对数组或容器中的元素进行排序。在 C++ 中,sort()
函数是由 C++ 标准库的<algorithm>
头文件提供的。- sort(start,end)左开右闭区间,默认从小到大
- sort是不稳定排序 可以改成稳定排序 stable_sort
sort的cmp和运算符重载
-
在比较函数排序中,每一次比较都要拷两个结构体过去,这样的速度是非常慢的。但如果是重载运算符,那么比较规则就本身就在结构体里面了,排序的时间会很快
-
bool operator<(const Node &other)const{ return a<other.a;//a是要比较的元素 }
-
使用示范
-
#include<cmath> #include<cstdio> #include<algorithm> using namespace std; struct Node{ double x,y,z; bool operator<(const Node &other)const{//重载小于运算符 return z<other.z; } } a[50050]; int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z); } sort(a,a+n);//每个点高度从小到大排序 double ans=0; double cx=a[0].x,cy=a[0].y,cz=a[0].z; for(int i=1;i<n;i++){ ans+=sqrt(abs(cx-a[i].x)*abs(cx-a[i].x)+abs(cy-a[i].y)*abs(cy-a[i].y)+abs(cz-a[i].z)*abs(cz-a[i].z));//两点的欧几里得距离 cx=a[i].x; cy=a[i].y; cz=a[i].z; } printf("%.3lf\n",ans);//输出保留三位小数 return 0;//华丽的结束 }
swap()
swap()
函数是一个简单的函数,用于交换两个变量的值。在 C++ 中,swap()
函数是由 C++ 标准库的<algorithm>
头文件提供的。
逗号运算符
- 逗号运算符是 C++ 中的一个二元运算符,它的作用是在同一个表达式中执行多个操作,并返回最后一个操作的结果。
四舍五入
b=int((b*10)+0.5)/10.0;//四舍五入到小数点后一位 b为double型
- +0.5的话,如果大于等于0.5就往前进一位,小于0.5就不往前进,然后强制转换到int会向下取整,正好四舍五入到整数,这是一种我认为最简单的四舍五入方法。
- 如果需要四舍五入到某一位,那么就*多少多少然后再除就好了
- 比如小数点后一位就*10/10.0
- 后两位*100/100.0
gcd()
gcd()
是求两个整数的最大公约数(Greatest Common Divisor)的函数。在 C++ 中,可以使用 <numeric>
头文件中的 gcd()
函数来计算最大公约数
%02d
%02d
是格式化字符串,它表示将后面传入的整数按照两位数进行格式化输出,并且如果位数不足两位,则在前面补 0。
snprintf()
-
snprintf()
函数是 C 标准库中的一个字符串处理函数,用于将格式化的数据写入到字符串缓冲区中。 -
该函数常用来快捷的将数转存于字符数组中,方便好用
-
**
snprintf
**传入四个参数-
要写入的字符数组
-
数组大小(一般用sizeof(ch)
-
要转的数的格式(和
printf()
类似) -
要转的数
snprintf(ch,sizeof(ch),"%lld",a);
-
回文
-
有偶数位的回文数除11外必定不是素数
bool ispalindrome (int a){ int s[20],l = 0; while (a){ s[++l] = a % 10; a /= 10; } for (int i = 0; i <= l/2; ++i) { if (s[i] != s[l - i]) return 0; } return 1; }
int和long long int
- int:
- 在大多数现代编译器和32位系统上,
int
类型通常占用4个字节(32位),其表示范围大约是 -2,147,483,648 到 2,147,483,647( − 2 31 到 2 31 − 1 -2^{31} 到 2^{31}-1 −231到231−1)。 - 在64位系统上,
int
类型通常仍然保持为4个字节,但在某些编译器和平台上,int
可能会被定义为8个字节(64位),这种情况下,其表示范围会更大。
- 在大多数现代编译器和32位系统上,
- long long int:
long long int
类型在所有平台上都至少占用8个字节(64位),其表示范围大约是 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807( − 2 63 到 2 63 − 1 -2^{63} 到 2^{63}-1 −263到263−1)。
toupper()
toupper()
是C语言标准库中的一个函数,用于将单个字符转换为对应的大写字母。这个函数定义在ctype.h
头文件中。如果c
是一个小写字母,toupper()
会返回对应的大写字母。如果c
不是小写字母,函数会返回原始字符。- ‘A’ 到 'Z’的范围:65-90
tolower()
tolower()
是C语言标准库中的一个函数,用于将单个字符转换为对应的小写字母。这个函数同样定义在ctype.h
头文件中。如果c
是一个大写字母,tolower()
会返回对应的小写字母。如果c
不是大写字母,函数会返回原始字符。这个函数不会改变任何非字母字符。- ‘a’ 到 ‘z’ 的范围:97-122
sprintf()
-
sprintf()
函数,是C语言标准库中的一个函数,用于将格式化的数据写入一个字符串。它的原型如下: -
int sprintf(char *str, const char *format, ...);
-
str
是目标字符串的指针,即你想要写入数据的地方。format
是格式化字符串,它定义了如何将后续参数转换为字符串。...
是可选的参数列表,根据format
中的格式指示符来提供相应的值。
-
sprintf()
返回写入的字符数(不包括结尾的空字符\0
)。如果目标字符串str
的大小不足以容纳所有数据,sprintf()
可能会导致缓冲区溢出,这是一个常见的安全问题。 -
使用示例:
-
char buffer[50]; sprintf(buffer, "The value is %d", 42); printf("%s\n", buffer); // 输出: The value is 42
sscanf()
-
sscanf()
是C语言标准库中的一个函数, 函数用于从字符串中读取格式化的数据。它的原型如下: -
int sscanf(const char *str, const char *format, ...);
-
str
是源字符串的指针,即你想要从中读取数据的地方。format
是格式化字符串,它定义了如何从字符串中解析数据。...
是指向变量的指针列表,用于存储解析出的数据。
-
sscanf()
返回成功匹配并赋值的参数数量。如果源字符串str
的格式与format
不匹配,或者没有足够的数据来满足format
的要求,函数可能会失败。 -
使用示例:
-
char input[] = "The value is 42"; int value; int result = sscanf(input, "The value is %d", &value); if (result == 1) { printf("Read value: %d\n", value); // 输出: Read value: 42 }
-
在现代C++编程中,由于
sprintf()
和sscanf()
可能导致缓冲区溢出,推荐使用它们的安全版本snprintf()
和sscanf()
。这些安全版本通过限制写入或读取的最大字符数来避免溢出。
isalpha()、isalnum()、isdigit()、islower()
-
在C语言中,
isalpha()
、isalnum()
、isdigit()
和islower()
是一系列用于检查字符属性的函数,它们定义在ctype.h
头文件中。这些函数通常用于字符串处理和输入验证。下面是每个函数的简要说明和用法: -
-
isalpha(): 这个函数用于检查一个字符是否是字母(大写或小写)。
int isalpha(int c);
如果
c
是一个字母,函数返回非零值(通常是1),否则返回0。 -
isalnum(): 这个函数用于检查一个字符是否是字母或数字。
int isalnum(int c);
如果
c
是字母或数字,函数返回非零值,否则返回0。 -
isdigit(): 这个函数用于检查一个字符是否是十进制数字(0-9)。
int isdigit(int c);
如果
c
是一个数字,函数返回非零值,否则返回0。 -
islower(): 这个函数用于检查一个字符是否是小写字母。
int islower(int c);
如果
c
是一个小写字母,函数返回非零值,否则返回0。 -
isupper(): 这个函数用于检查一个字符是否是大写字母。
-
-
这些函数通常与
isspace()
(检查空白字符)、isupper()
(检查大写字母)等其他字符检查函数一起使用。它们在处理用户输入、解析文本数据或执行文本格式化时非常有用。
getline()
-
getline()
是C++标准库中的一个函数,用于从输入流(如std::cin
)读取一行文本,直到遇到换行符(通常是\n
)或者达到指定的分隔符。这个函数定义在<string>
头文件中。getline()
函数的原型如下: -
std::istream& getline(std::istream& is, std::string& str, char delim);
-
is
是输入流的引用,通常是std::cin
。str
是一个std::string
对象,用于存储读取的文本。delim
是可选的分隔符,如果提供,getline()
会在遇到这个分隔符时停止读取。如果不提供,它默认读取到换行符。
cin
cin
默认会跳过空白字符(如空格、制表符和换行符),直到遇到下一个非空白字符。这意味着如果你想要读取包含空格的字符串,你需要使用getline()
或者在读取时指定分隔符。
size_t
- 是 C++ 标准库中定义的一个无符号整数类型,用于表示内存中某个对象或容器等数据结构的大小或索引。具体而言,
size_t
的值通常是一个与机器相关的、能够表示当前机器上最大可能内存块大小的无符号整数。
npos
npos
是 C++ 标准库中定义的一个常量,用于表示字符串或容器等类型中不存在某个特定子串或元素时的返回值。具体而言,npos
的值是一个无符号整数,它通常被定义为最大的可能的size_t
值。
find()
-
find()
是 C++ 标准库中字符串类(如std::string
)和容器类(如std::vector
)等类型的成员函数之一。它用于在字符串或容器中查找某个特定的子串、元素或者值,并返回第一个匹配项的位置。 -
具体而言,
find()
函数的使用方式如下:cppCopy Codesize_type find(const T& value, size_type pos = 0) const;
其中,
T
可以是字符类型(char
、wchar_t
等)、字符串类型(const char*
、const wchar_t*
等)或者容器类型中的元素类型。value
是要查找的目标值,pos
是查找的起始位置,默认为 0。find()
函数会从指定的起始位置开始,在字符串或容器中顺序查找目标值。如果找到了目标值,则返回第一个匹配项的位置;如果没有找到目标值,则返回一个特殊的值npos
,表示未找到。 -
需要注意的是,对于字符串类型和容器类来说,
find()
函数还有其他几个重载版本,可以根据具体情况进行不同类型的查找。例如,还可以指定要查找的子串的起始位置和长度,或者使用谓词函数进行自定义的匹配条件判断。同时,对于多个匹配项的情况,可以使用find_first_of()
、find_last_of()
、find_first_not_of()
和find_last_not_of()
等函数进行更详细的查找操作。
count
-
count()
是 C++ 标准库<algorithm>
头文件中的一个函数,用于统计容器中某个值(或满足某个条件)出现的次数。它可以用于各种类型的容器,如数组、vector、list、map 等。 -
for (int i = 0; i < 27; ++i) { b[i] = count(s.begin(),s.end(),a[i]);//统计a[i]在s中出现的次数,string s; }
高精阶乘
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= ws; ++j) {
a[j] = a[j] * i + jw;
jw = a[j] / 10;
a[j] %= 10;
}
while (jw > 0) {
ws++;
a[ws] = jw % 10;
jw /= 10;
}
}
nth_element()
-
nth_element()
是C++标准模板库(STL)中的一个算法函数,它用于部分排序一个序列,使得序列中的某个特定位置(第n个位置)的元素被放置在如果整个序列完全排序时它应该在的位置。这个函数不会对整个序列进行完全排序,而是只保证第n个元素之前的所有元素都不大于它,第n个元素之后的所有元素都不小于它。 -
nth_element()
的原型如下:template<class RandomIt> void nth_element(RandomIt first, RandomIt nth, RandomIt last);
或者,如果你需要自定义比较函数,可以使用以下重载:
template<class RandomIt, class Compare> void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp);
first
和last
是指向要排序序列的迭代器。nth
是指向序列中第n个位置的迭代器。comp
是一个可选的比较函数,用于定义元素之间的比较方式。
nth_element()
的时间复杂度在平均情况下是线性的 O(n),但在最坏情况下可能会退化到 O(n^2)。然而,对于随机数据,它通常表现得非常好,因为它基于快速选择算法(Quickselect)。使用
nth_element()
的一个典型场景是当你只需要找到序列中的中位数(第n个元素,其中n是序列长度的一半)而不需要对整个序列进行排序。例如,你可以使用nth_element()
来找到序列的中位数,而不需要对整个序列进行完全排序。
C++整数快读
inline int read(){ //快读 inline 关键字告诉编译器尝试将这个函数的代码直接插入到调用它的地方,以减少函数调用的开销。这通常用于小函数,以提高程序的执行效率。
char ch=getchar();
int x=0,f=1;
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while('0'<=ch&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
setw()
-
使用
setw()
的目的通常是为了格式化输出,使得输出的文本在视觉上对齐。例如,如果你想要输出一系列数字,并且希望它们在输出时对齐,你可以使用setw()
来设置每个数字的宽度。 -
使用
setw()
的示例: -
#include <iostream> #include <iomanip> // 包含 iomanip 头文件以使用 setw() int main() { int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int width = 5; // 设置字段宽度为5个字符 for (int number : numbers) { std::cout << std::setw(width) << number << " "; } std::cout << std::endl; return 0; }
-
在这个例子中,
setw(5)
设置了输出流的字段宽度为5个字符。这意味着每个数字将占据至少5个字符的空间,如果数字本身长度小于5,那么它会在左侧填充空格。输出结果将是: -
1 2 3 4 5 6 7 8 9 10
next_permutation()
-
next_permutation()
是 C++ 标准库中的一个函数,它用于生成序列的下一个排列。这个函数定义在<algorithm>
头文件中。next_permutation()
会尝试将给定的序列(如一个整数数组)重新排列,使其成为字典序中的下一个较小排列。如果序列已经是字典序中的最大排列(即无法生成更大的排列),则函数会将序列重置为字典序中的最小排列(即全排列的第一个)。next_permutation()
, 如果找到了下一个排列,函数返回true
,否则返回false
(在这种情况下,序列已经被重置为最小排列)。在实际使用中,你可以利用这个返回值来控制循环的执行。 -
#include <iostream> #include<algorithm> #include <iomanip> #define width 5 using namespace std; int main() { int num[9]={1,2,3,4,5,6,7,8,9},n; cin>>n; do { for (int i = 0; i < n; ++i) { cout<<setw(width)<<num[i]; } cout<<endl; }while(next_permutation(num,num + n)); return 0; }
prev_permutation()
- 在C++中,
prev_permutation()
是一个标准库算法,它用于生成序列的上一个排列。这个函数定义在<algorithm>
头文件中。prev_permutation()
会尝试将给定的序列(如一个整数数组)重新排列,使其成为字典序中的上一个较小排列。如果序列已经是字典序中的最小排列(即无法生成更小的排列),则函数会将序列重置为字典序中的最大排列(即全排列的最后一个)。prev_permutation()
,如果找到了上一个排列,函数返回true
,否则返回false
(在这种情况下,序列已经被重置为最大排列)。在实际使用中,你可以利用这个返回值来控制循环的执行。 - 使用同
next_permutation()
二分查找
lower_bound
:lower_bound
查找的是第一个不小于(即大于或等于)给定值的元素的位置。如果所有元素都小于给定值,它返回指向容器末尾的迭代器。- 如果容器是有序的,并且元素是唯一的,
lower_bound
返回的是第一个等于给定值的元素的位置。
upper_bound
:upper_bound
查找的是第一个大于给定值的元素的位置。如果所有元素都小于或等于给定值,它返回指向容器末尾的迭代器。- 如果容器是有序的,并且元素是唯一的,
upper_bound
返回的是第一个大于给定值的元素的位置。
lower_bound(a+1,a+n+1,x)
欧拉筛素数
const long long N = 100005;
long long cnt = 0,prime[N + 1];
bool vis[N];
void sieve () {
vis[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!vis[i])
prime[cnt++] = i;
for (int j = 0; j < cnt && i * prime[j] <= n; ++j) {
vis[i * prime[j]] = 1;
if (i % prime[j] == 0)
break;
}
}
}