机试,蓝桥,PAT常用,一定要记住的!!!

常用笔记

1. 排序

algorithm 默认是从小到大

  • 对于int arr[10] 数组,sort(a, a+10);
  • 对于vector <int> v(10) , sort(v.begin(),v.end());
    传入了参数cmp后,根据cmp进行排序
bool cmp(int a, int b){
    
    //cmp函数返回的值是bool类型
	return a>b; //从大到小排列,不能写成含有等号的不等式,sort是不稳定的排序
}

sort在结构体中的应用:
结构体:

typedef struct Pat{
    
    
	int num;
	string sid;
	int age;
}PAT; //相当于struct Pat   
PAT stud[mMax] //定义一个结构体变量 mMax结构体数组的大小 
for(int i=0;i<n;i++){
    
    
		cout<<pt[i].sid<<endl; }//结构体的遍历

cmp函数:

bool cmp(PAT a,PAT b){
    
    
	if(a.age>=60&&b.age>=60){
    
    
		return a.age==b.age? a.num<b.num:a.age>b.age;
	}
	else return ..... 
}

叮叮~具体应用可以参考本人写的文章:北大机试题:病人排序

2. 数学类

2.1 最大公约数

int gcd(int a, int b){
    
    
	return b==0? a : gcd(b, a%b);
	}
int gcd(int a,int b){
    
    
	if(b==0) return a;
	return gcd(b,a%b)
最大公倍数 =  a* b / gcd(a,b)

素数

== 1既不是素数,也不是合数 ==

include <cmath>
bool isprime(int n){
    
    
	if(n <= 1) return flase;
	int sqr = (int) sqrt(1.0 *n); //sqrt是参数要求是浮点型
	for(int i=2;i<=sqr;i++){
    
    
		if(n%i==0) return flase;
	}
	return true;
如果n没有靠近,int型变量的范围上界。则:
bool isprime (int n){
    
    
	if(n<=1) return false;
	for(int i=2; i*i <= n;i++){
    
    
		if(n%i==0) return false;
	}
	return true;
}
注意i*i可能会溢出的问题,但是如果定义成long long 就不会
素数表的获取,复杂度为O(nsqrt(n)),对于n不超过10^5
const int maxn = 110//表长
int prime[maxn], pnum = 0;
bool p[maxn] = {
    
    0} //标记i是否是素数;
for(int i=0;i<maxn;i++){
    
    
	if(isprime(i)){
    
    
		 prime[pnum++] = i;
		 p[i] = true;
	}
}
素数筛选发的获取,复杂度为O(nlog~n~),对于n不超过10^5
const int maxn = 110//表长
int prime[maxn]={
    
    2}, pnum = 1;
bool p[maxn] = {
    
    0} ; //标记i是否是素数,i=0,为素数,i=1不是素数;
for(int i=2;i<maxn;i++){
    
    
	if(!p[i]){
    
    
		 prime[pnum++] = i;
		 for(int j=i+i;j<maxn;j+=i){
    
    
		 	p[i] = true;
		 }
	}
}

104个素数大概其最大值达到了107

大整数运算

数据的存储

  1. 整数的高位存储在数组的高位,整数的低位存储在数组的低位。 对于字符串读入之后,需要对存储的数组进行反转。
struct bign{
    
    
	int d[1000];
	int len;
	bign(){
    
    
		memset(d,0,sizeof(d));
		len = 0;
	}
bign change(char str[]){
    
    
	bign a;
	a.len = strlen(str);
	for(int i=0;i<a.len;i++){
    
    
		a.d[i] = str[a.len-i-1] - '0'; //顺序相反
	}
	return 0;
}

高精度加法

一次对应遍历数据的每一位,然后对应相加,得到结果个位数作为该位结果,十位数作为新的进位。

bign add(bign a,bign b){
    
    
	bign c;
	int carry = 0;
	for(int i=0;i<a.len||i<b.len;i++){
    
     //一较长的为界限,一开始已经为bign类型的实例赋予了初值。
		int temp = a.d[i] + b.d[i] +carry;
		c.d[c.len++] = temp %10;
		carry = temp / 10;
	}
	if(carry != 0){
    
    
		c.d[c.len++] = carry; //注意最后的进位
	}
	return c;
}

高精度减法

一次对应遍历数据的每一位,然后对应相减,如果不够减则令被减为高为减一,被减为加10,在继续减法。如果够减,直接减。最后一步要注意减法后高位可能有多余的0,则忽视他们。如果减数大于被减数,在减之前需要交换两者的位置,然后添加符号。

bign add(bign a,bign b){
    
    
	bign c;
	for(int i=0;i<a.len||i<b.len;i++){
    
     //一较长的为界限,一开始已经为bign类型的实例赋予了初值。
		if(a.d[i]<b.d[i){
    
    
			a.d[i++] -= 1;
			a.[i] += 10;
		}
		c.d[c.len++] = a.d[i]- b.d[i];
	}
	while(c.len-1>=1&&c.d[c.len-1] == 0){
    
    //至少保留一个0,除去大整数高位上多余的0
		c.len--;
	}
	return c;
}

高精度与低精度的乘法

将低精度的数据看成一个整体,将高精度的每一位与低精度相乘,将相乘结果的个位数作为该位的结果,其他位作为进位与其他相乘结果继续相加,并且相加之后,以同样的方式进行下一位的运算。
如果两个数中只有一个符号,则最后的时候再添加负号,一开始都以绝对值进行计算。

bign multi(bign a,int b){
    
    
	bign c;
	int carry = 0;
	for(int i=0;i<a.len;i++){
    
    
		temp = a.b[i] *b + carry;
		c.b[c.len++] = temp % 10;
		carry = temp / 10;
	}
	while(carry != 0) {
    
    
		c.d[c.en++] = carry % 10;
		carry / = 10;
		}//这个进位不仅仅只有1位
	return 0;
}

高精度与低精度的除法

上一步的余数乘以10加上该步的位,得到该步临时的被除数,将其与除数相比较;如果不够除,则该位的商为零;如果够除,则上即为对应的商,余数即为对应的余数。

bign divide(bign a,int b,int & r){
    
    
	bign c;
	c.len = a.len;
	for(int i = a.len -1;i >= 0;i--){
    
     //从最高位开始
		r = r*10 + a.d[i];
		if(r<b) c.d[i] = 0;
		else{
    
    
			c.d[i] = r/b;
			r = r % b;
		}
	}
	while(c.len - 1 >= 1 && c.d[c.len -1] == 0){
    
    
		c.len--;
	}
	return c;
}

组合与排列

n!中有多少个质因子P

n! =

int cal(int n,int p){
    
    
	int ans = 0;
	while(n){
    
    
		ans += n/p;
		n /= p;
	}
	return ans;
}

int cal(int n,int p){
    
    
	if(n==1) return 0;
	return n/p + cal(n/p , p); 
	}

组合数的计算

在这里插入图片描述

定义法:

在这里插入图片描述
当 n 超过20就不可取。

long long c(long long n,long long m){
    
    
	long long ans = 1;
	for(long long i=1;i<=n;i++){
    
    
		ans *= i;
	}
	for(long long i=1;i<=m;i++){
    
    
		ans /= i;
	}
	for(long long i=1;i<=n-m;i++){
    
    
		ans /= i;
	}
	return ans;
}

递推公式法

从n各不同的数中选m个数的方案数,可以转化为:1.不选最后一个,再后面的n-1个数中选出m个数。2. 选最后一个,再后面的n-1个中选出m-1个即可。
在这里插入图片描述
在这里插入图片描述

long long c(long long n,long long m){
    
    
	if(m==0||m==n) return 1;
	return c(n-1,m)+c(n-1,m-1);
}

3. 分割数的用法

回文

//回文 int palindrome = 0 
while(c){
    
    
	d = c %10; //%1000 就表示取后3位
	c = c/10;
	palindrome = palindrom*10 + d;
	}

将数分成左边和右边

int a = 1 ,n;   //a 取 1则 ,中间的数的位置在len-1的位置,a = 10,则在len -2的位置
while(n/a!=0){
    
    
	left = n/(10*a);
	now = n/a%10;
	right = n%a;
}

4. ASCII码表

字符0 - 9:    ==48~57==
字符A - Z:    ==65~90==
字符a - z:    ==97~122==            `//a-A=32`
字符space(空格):   ==32==          

5. cctype中的判断字符的函数:

①isalnum: 判断是否是字母或者是数字 ,相当于:

if ( (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ) return true;

②isalpha 判断是否是字母;③isdigit 判断是否是数字;④isupper 判断是否是大写字母;⑤islower 判断是否是小写字母;⑥isbland 判断是否是空格/tab键;⑦isspace 判断是否是空格/tab键/回车;

对于大小写的转换

  • char supper_alpha = lower_alpha - 32
  • char t = tolower( c ); // 将c字符转化为小写字符赋值给t,如果c本身就是小写字符也没有关系
  • char t = toupper( c ) ; // 换大写

6. string的使用

头文件:string

  • 由于string是C++中特有的,因此只支撑cin, cout;
string s = "hello world"; // 赋值字符串
string s2 = s;
string s3 = s + s2; // 字符串拼接直接⽤+号就可以
string s4;
cin >> s4; // 读⼊字符串
cout << s; // 输出字符串

在 string s 后只能加字符 s += b;
在 string s 前只能加字符 s = a + s; // a可以是 char 型也可以是 string 类型

  • cin 读字符串的时候,是以空格为分隔符的,如果想要读空格的字符串,就需要getline;
string s; // 定义一个空字符串s
getline(cin, s); // 读取空格的字符串,包括空格
  • 长度可以通过 s.length() 获取~(有多少个字符就是长度度多少,不存在 char[] 末尾的结束符之类的~),如果想要直接遍历s,中的每个元素的话跟数组的差不多;
int len = s.length();
		for(int i=0;i<len;i++){
    
    
			if(isdigit(s[i])) {
    
    
				num ++;  //计算s中数字的个数
				}
		} 

6.1string中的函数

  1. string.insert().
    insert(pos , string) 在pos号位插入字符串string
    insert(it,it2,it3) ,it 位原字符串的预插入位置,it2 和it3 为待插入字符串的首位迭代器,用来表示[it2,it3)被插在it的位置上.
string str = "asdfg",str1 = "opy";
str.insert(str.begin() +2,str1.begin(),str1.end()); //只能用迭代器方式进行访问
cout<<str<<endl;

在这里插入图片描述

  1. string.substr() 截取
string str = "2019-05-11"
string all = str.substr()
string y = str.substr(0,4) //从下标0开始向后截取4位,y = 2019;
string m = str.substr(5,2)
string d = str.substr(8);//从下标为8开始到结尾的全部字符,d = 11;
  1. string.erase(pos)
    str.erase(pos); 删除str中下标pos到末尾的所有字符
    str.erase(first,num) ; // 删除从first 开始num个字符
    在科学计数法中使用erase删除前导零的方法:
if(s[i]=='0'){
    
    
	s.erase(s.begin());
}
  1. string.find()函数
    str.find(2);返回字符串2在str中起始的位置,如果没有找到返回-1;
    str.find(a,num);从字符串str下标为num开始查找第一个出现字符串a,若找到返回起始位置,找不到则返回-1;

7. 字符串反转

头文件:algorithm reverse函数
reverse(s.begin(),s.end());

8. 容器

vectorstackqueuemapset 这些在C++中统称为容器,这些大小可以用.size()获取。

8.1 vector (向量/动态数组)

vector 定义

  • vector <int> v // 没有分配大小,v.size()为0.
  • vector v(10) // 定义一个长度为10的int数组,默认10个元素值都为0,
  • vector v3(100, 9);// 把100⻓度的数组中所有的值都初始化为9
  • vector v1; v1.resize(8); //先定义⼀个vector变量v1,然后将⻓度resize为8,默认这8个元素都是0

vector 遍历

for (auto it = c.begin(); it != c.end(); it++) {
    
     
cout << *it << " "; // 使⽤迭代器的⽅式访问vector
}
for (int i = 0; i < c.size(); i++) {
    
    
cout << c[i] << " ";
}

vector中常用函数

  1. push_back(x) 就是在vector后面添加一个元素x
  2. pop_back() 删除vector的尾元素
  3. size() 计算vector 的动态数组长度
  4. clear()
  5. insert()
    vector v{1, 2, 3, 4};
    v.insert(v.begin()+2, 5); // {1, 2, 5, 3, 4}
    v.insert(v.begin(), 2, -1); // {-1, -1, 1, 2, 5, 3, 4}

8.2 map(映射)

在头文件==<map>==中:

8.2.1如何理解map中的映射:

  • 相当于array[0] = 5.20,是将int 型映射到double型。
  • map 可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器)。

8.2.2如何定义map:

  • 字符串到整型的映射:map<string,int> mp; 字符串必须只能用string表示。
  • 字符型到整型的映射:map<char,int> mp;
  • set容器到字符串类型的映射:map<string,set<int>> mp;可以表示mp[“paopao”] = {11,12,15,16,17},并且里面的值是不能相同,按照升序的顺序排列。具体例题可见:1022 Digital Library

8.2.3map的访问:

  1. 通过下标访问:
map<char,int> mp;
mp['c'] = 20;
mp['c'] = 30printf("%d\n",mp['c']); // 结果为30
  1. 通过迭代器访问
for(auto it = j.begin(); it!= m.end();it++){
    
    
	cout<< it->fist<<" "<< it->second << endl;
}
// 访问map的第⼀个元素,输出它的键和值
cout << m.begin()->first << " " << m.begin()->second << endl;
// 访问map的最后⼀个元素,输出它的键和值
cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
// 输出map的元素个数
cout << m.size() << endl;

8.2.4map常用函数:

  1. find()
    find(key)返回键为key 的映射的迭代器,时间复杂度为O(logN),N为map中映射的个数。
  2. erase()
    删除单个元素:mp.erase(it) // it为迭代器;mp.erase(‘b’)
    删除一个区间内的所有元素:mp.erase(first,last) //
  3. size() 获得map映射的对数
  4. clear() 清空map
map<char,int> mp;
mp['a'] = 1;
map <char,int> mp;
int main(){
    
    
	mp['a'] = 1;
	mp['b'] = 2;
	auto it = mp.find('a'); //auto 可以让编译器根据初始值类型直接推断变量的类型
	printf("%c %d\n",it->first,it->second);
	mp.erase(it,mp.end());//删除it之后的所有映射。
	mp.erase(it) //就把mp['a']删除了
	mp.clear();
}

8.2.5常见用途:

  1. 需要建立字符(或字符串)与整数之间映射的题目,使用map可以减少代码量。
  2. 判断大整数或者其他类型数据是否存在的题目,可以把map当bool数组用
  3. 字符串和字符串的映射也可能会遇到。
    叮叮~具体应用可以参考本人写的文章:PAT1018

8.3set(集合)

因为是集合所以有着互异性,set里面的各元素是各不相同的,而且set会按照元素进行从小到大排序

8.3.1set的定义

set<int> s; 定义一个空集合s,其中typename 中可以是double,结构体,类,或者是其他容器。
set<double> t[n] ; 则每个t[0]~t[n-1]每一个都是一个set容器。

8.3.2set内元素的访问

只能通过迭代器访问,例如:set <int> :: iterator it;

for(set \<int> ::iterator it = s.begin();it!= s.end();it++){
    
    
		printf("%d",*it)
}

或者,将set <int> ::iterator 用auto 表示

8.3.3set常用函数:

  1. insert()
for (int i = 0; i < 6; i++) {
    
    
s.insert(i); // 向集合s⾥⾯插⼊i
}
  1. find()
*(s.find(2))  // 如果2存在,则printf 结果为2。
s.find(2)!=s.end() // 判断该元素是否存在
  1. erase()
    s.erase(s.find(1)) // 删除单个元素 ,这个方法空间复杂度为0(1)
    s.erase(100) // 删除的单个元素,这个是个为O(logn)
    s.erase(s.find(300),s.end()) // 删除元素300到set末尾之间的元素
  2. size()
    所有容器通用的获得容器大小的函数。
    s.size()
  3. clear()
    s.clear() //清空set 容器,则s.size() = 0;

8.4 stack

头文件在<stack> 中,加上命名空间。

8.4.1 stack 的定义

stack <int> s; // 类型和上面的容器相同,可以是基本数据类型或者容器

8.4.2 stack 容器内元素的访问

这里的栈和数据结构中的栈一样,只能通过top()来访问栈顶元素

for (int i = 0; i < 6; i++) {
    
    
s.push(i); // 将元素i压⼊栈s中
}
while(s.size()!=0){
    
    
	cout << s.top() << endl; // 访问s的栈顶元素
	s.pop(); //弹出栈顶元素
} // 相当于遍历所有的元素,并且遍历完后s 中的元素会被清空。

8.4.3stack常用函数:

  1. push()
  2. pop()
  3. top()
  4. size()
  5. empty() // 检测stack内是否为空,返回ture为空,返回false为非空

8.5 queue队列

头文件在<queue> 中,加上命名空间。

8.5.1 queue 的定义

queue <int> q; // 类型和上面的容器相同,可以是基本数据类型或者容器

8.5.2 queue 容器内元素的访问

这里的队列和数据结构中的栈一样,只能通过front()来访问队首元素,或者用back()来访问队尾元素。

queue<int> q; // 定义⼀个空队列q
for (int i = 0; i < 6; i++) {
    
    
q.push(i); // 将i的值依次压⼊队列q中
}
printf("%d %d\n",q.front(),q.back()); // 访问队列的队⾸元素和队尾元素  ,结果为1 5
cout << q.size() << endl; // 输出队列的元素个数
q.pop() //弹出首个元素

8.5.3queue常用函数:

  1. push()
  2. pop()
  3. front()
  4. back()
  5. size()
  6. empty() // 在使用front和pop()前,最好判断下队列是否为空。

9. 全排列

头文件:algorithm中:
按照字典升序:
next_permutation(start,end):
数组中的使用:

do{
    
      
    for(int i=0;i<n;i++) cout<<a[i];
    printf("%\n");
}while(next_permutation(a,a+n)); //n表示对前几个进行全排列 

string中的使用:

do{
    
    
	cout<<s<<endl; 
	}while(next_permutation(s.begin(),s.end()));

注意:在使用next_premutation()前需要进行升序排列,否则会出现减少排列的结果。

按照字典降序:prev_permutation(start,end)。
具体应用可以参考本人写的博客:试题全排列

10. memset()

头文件:cstring 或 memory中:
memset是以字节为单位,初始化内存块。

  • 当初始化一个字节单位的数组时,可以用memset把每个数组单元初始化成任何你想要的值,比如,
char data[100];
memset(data, 1, sizeof(data));    
memset(data, 0, sizeof(data));    

2.对于其他类型就需要注意,一般都只会用初始化为0的

int data[10];
memset(data, 0, sizeof(data));    
memset(data, -1, sizeof(data));    

注意:如果对int类型数组赋值为1的话就会出现问题:因为一个int类型的变量占4个字节,而memset是将每一个字节初始化成1,所以一个int类型的变量被初始化成了0x01010101。而这个数是16843009
补充:对于全部赋值为0,int a[10] = {},或者int a[10] = {0};

11. 变量类型的区分

  • 整型:
    int:取值范围:-231~+(231-1),32位整数,一般记住109范围以内的整数就可以定义为int型。
    long:取值范围:-263~+(263-1),64位整数,一般记住1010 ~1018以内的整数就可以定义为int型。其中需要注意,long long型赋值大于231-1的初值时,需要在初值后面加上LL。
    例如: long long a = 123456789123LL;
  • 浮点型
    float:取值范围:-2128~+(2128),一般记住有效精度是6-7.
    double:取值范围:-21024~+(21024),一般记住有效精度是15-16.
    -字符型
    注意:字符常量必须用单引号标注
  • 常量定义,const 与define
    const 可以定义常量的类型 例如:const int a = 100;
    define 可以定义语句或片段 例如:#define ADD(a, b) ((a)+(b)) 必须要加括号,防止宏定义中部分替换而导致的运行错误。
    叮叮~具体应用可以参考本人写的文章:PAT 1065

12.运算符

  • 除法运算符:整数与整数相除下取整,结果值是舍去小数部分(下取整),如:5/6=0;
  • 位运算:一般常用是<<,用来表示无穷大:(1<<31-1)其等价于const int inf = 230-1。注意位运算的优先级没有算术运算符高

13.输入输出

在<cstdio>有文件中:

  • scanf:
  1. 除了字符串(char 数组)外,其他都需要加&,如:char a[10] scanf("%s",a),因为a本身就是代表着第一个元素的地址。
  2. 除了%c外,scanf对其他格式(如%d,%s,……)的输入是以空白符(即空格、Tab)为结束判断标志的。如:
    scanf("%d%c%s",&a,&b,c); //input : 1 a abc
    则输出:a=1,b= ,c=a;
  • printf:
  1. 值得注意的是:scanf中的double类型是lf,而printf中的double是f。
  2. 建议浮点数尽量都用double定义,因为在进行四则运算时精度值能较为稳定保证要求。
    不过一般都无法完全保证没有误差,具体可见本人之前写过的一篇博客:北大机试题目的一个坑点就是浮点数的精度问题
    浮点数的比较不能直接 == 比较,因为根据计算机中浮点数的表示方法,对同一个小数,当同精度表示时,结果是不一样的:
    如 float 的 0.1 和 double 的 0.1 ,直接用就会输出不相等,所以可以使定义 eps = 1e-8 进行浮点数的比较:
const double eps = 1e-8;
#define Equ(a, b) ((fabs((a) - (b))) < (eps))
#define More(a, b) (((a) - (b)) > (eps))
#define Less(a, b) (((a) - (b)) < (-eps))
#define LessEqu(a, b) (((a) - (b)) < (eps))
if(Equ(a, b)) {
    
    
 cout << "true"; }
  1. %md可以使不足m位的int型变量以m位进行右对齐输出(向前补空格),其中高位用空格补齐;如果变量本身超过m位,则保持原样。
    %0md则是向前补0。
    %.mf可以让浮点数保留m位小数输出,这个“保留”使用的是精度的“四舍五入成双”规则。如果要是只要保留小数点后两位,其他直接舍去的话就需要这样处理:printf("%.2lf",(int)(r*100)/100.0);
  2. 对于输出格式要求一行内相隔空格的输出,可以先输出第一个,或者分开输出最后一个。
  • getchar
    一般用于scanf单独输入字符型数据时,用于去除<enter>键.
  • getline
    用于代替cin中输入带个空格的字符串。
  • sscanf()ssprintf()
    可以理解为:string+scanf(),可以用于将字符数组的内容以“%d”的格式写入到n1中;
    string+printf(),将n以“%d”的格式写到str字符数组中;
int  n1,n2=555;
char str1[4] = "123",str2[4];
sscanf(str1,"%d",&n);
printf("%d\n",n1);  //n1 = 123;
sprintf(str2,"%d",n2);
printf("%s\n",str2);  //str2 = "555";
##经常应用于时间表:
int h = 12, m = 15, s = 22; 
char str1[100], str2[100]="2020年5月7日星期四";
sprintf(str1, "%s %d:%d:%d",str2,h,m,s);
printf("str = %s\n",str1);  //str1 = "2020年5月7日星期四 12:15:22";

13.math函数

  • fabs(double x) double 型取绝对值。
  • floor(double x)ceil(double x型变量的向下取整和向上取整,返回类型还是double 如:
double a = -3.2,  b = 3.2;
printf("%.0f %.0f\n",floor(a),ceil(a));
printf("%.0f %.0f\n",floor(b),ceil(b));
//output:
-4 -3
2  4
  • pow(double r, double p) :rp,注意r和p,返回值都是double型的
  • sqrt(double a) a1/2,返回double类型的算术平方根
  • log(double x) 返回double类型的以e为底的对数。logab = logea / logeb ;
  • sin(double x)cos(double x),tan(double x)asin(double x) 反正弦值,acos(double x) ,atan(double x)
    通常可以把pi 定义为 ,const double PI = acos(-1.0)。
  • round(double x) 将double型变量x四舍五入,需要进行取整。如:
    a = (int)round(3.5) // a = 4;

补充: 实现四舍五入
1.(int)(a+0.5) //想要保留几位,就先将a乘以几位数:(int)(a*1000+0.5)/1000.0,保留3位小数,输出用%.3f输出

  • 正弦值、余弦值和正切值的函数:sin()cos()tan()

14.cstring

主要用于字符数组的函数。
补充知识:
在数组中只有字符型的数组末尾有一个\0表结束符。

  • strlen()可以得到字符数组中第一个\0前的字符的个数。如:
    int len = strlen(a) // char a[5] 则len = 5
  • strcmp()函数返回两个字符串大小的比较结果,比较原则按字典序,其返回值为((<)负整数,(==)0,(>)正整数)相当于bool型。对于string类型的字符串则可以进行比较,就可以返回bool型;
    如:
char a[5]="acdeg", b[4]="aceg";
string c="acdeg",d="acdeg";
int cmp = strcmp(a,b);
if(cmp>0) printf("字符串a大于字符串b")
if(c>d)  printf("字符串c大于字符串d");
  • strcpy()函数把一个字符串复制给另一个字符串,如:
    strcpy(str1,str2); 把字符数组str2复制给字符数组str1;
  • strcat()把一个字符串接到另一个字符串后面,如:
    strcat (str1,str2);把字符数组str2接到字符数组str1后面

对于字符串数组的表示方法

  1. 二维数组数组表示法:list[strnum][strlength] ,一般strlength题目中会给固定字长
  2. string 类表示方法 :string list[strnum]
    当strnum 数组超过10000时,一般不能使用第二种方法,用string需要用到流的输入输出,耗时较大。

15.复杂度

  • 时间复杂度:对于一般的oj系统来说,一秒能承受的运算次数大概是107~108
  • 空间复杂度:107 的数组为限制。

16.正三角

1+2+3+……+x = ((1+x)*((1+x)/2))/2

17.日期

  1. isleap( (year %4==0&&year%100!=0)||year%400==0) //闰年
  2. 对于整型的数值中日期的输出,printf(“%04d-%02d-%02d”,yy,mm,dd);

18.类型转换

在头文件 <string>

对于int类型与char类型的转换 常用

  • int 转 char: char alpha = a +‘0’ // a 为int 类型
  • char 转 int : int num = alpha - ‘0’

对于数字类型(int,double,float)与string类型的转换

  • int 转string类型: to_string(123); // 转成字符串123
  • double 转string类型: to_string(4.5); //转成字符串4.5
  • string 转 int 型: string str = “123.4”, int a = stoi(123) // 对于字符中不是整型的部分会采用截取的方式,但如果最前面不是数字或小数点,会运行时发生错误。

以此类推:还有stof(string to float) , stold (string to long double) , stol (string to long), stoll(string to long long),stoull(string to unsigned long), stoull(string to unsigned long long)。//不过在蓝桥中的DEV不是最新版本,因此这些函数还是不能使用,尽量用第一种方法。

19.algorthim中常用的函数

需要添加命名空间才能使用,using namesapce std;

19.1max(x,y),min(x,y)

其参数可以是浮点型,也可以是整型,如果想要比较三个数的大小,可以采用嵌套的方式:
max(x,max(y,z))。

19.2 abs(x) 取绝对值

其跟fabs()的区别在于,abs函数的参数只能是整型,fabs只能用于浮点型。
注意 绝对值函数仅仅只是对参数进行取相反数,并不改变原始值,如果需要改变原始值的话就需要用 n = abs(n) 。当然也可以直接取反n = -n ;

19.3swap()交换x,y的值

19.4reverse()

int a[9] ={
    
    1,2,3,4,5,6,7,8,9};
reverse(a,a+9) //a[9] = {9,8,7,6,5,4,3,2,1}
string  str = "qwert";
reverse(str.begin()+1,str.end()) // str = "qtrew";
reverse(str.begin()+1,str.begin()+3) // str = "qewrt";

19.4next_permutation()

查看目录全排列,有详细内容。

19.5fill()

  • 把数组或容器中的某一段区间赋值为某个相同的值。弥补了memset字节赋值的不便,fill()可以赋值数组类型对应范围中的任意值。
    fill (a,a+5,23344); // 将int 类型数组a 中 a[0] ~ a[4] 均赋值为23344

19.6sort()

在目录中,1.排序中有详解。

20 lower_bound() 和 upper_bound()

  • lower_bound(first, last, val)
    寻找在数组或容器[first ,last) 范围中第一个值小于等于val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
  • upper_bound(first, lasrt, val)
    寻找[first,last)范围内第一个值大于val的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。

21 快速幂

对于a ,b 中存在大于1e+9;

  1. 如果b是奇数
    ab = a * ab-1
  2. 如果b是偶数
    ab =ab/2*ab/2
//采用递归的方式:
typedef long long LL;
LL binaryPow(LL a, LL B, LL m) {
    
    
	LL t;
	if(b == 0) return 1; //如果b为0,那么a^0=1
	if(b%2==1) return a*binaryPow(a, b-1, m) % m;
	else{
    
    
		t = binaryPow(a,b/2,M);
		return t*t%m;
	}
// a^13%m = a^8*a^4*a^1%m
2^3 + 2^2 + 2^1;
typedef long long LL;
LL binaryPow(LL a,LL b, LL m) {
    
    
LL ans = 1;
	while(b>0){
    
    
		if(b&1){
    
    //相当于if(b%2)
		ans = ans *a %m; // 令ans累积上a
		}
		a = ans *a%m; //令ans累积上a
		b>>=1; //将b的二进制右移一位,即b = b>>1或b = b/2
	}
	return ans;
}

注意:
3. 如果初始时a有可能大于等于m,那么需要在进入函数前就让a对m取模
4. 如果m为1,可以直接子啊函数外部特判为0,不需要进入函数计算(因为任何正整数对1取模一定等于0)。

two pointers

应用领域:

  1. 一个递增数组中,找到连个元素的和等于一个值m,采用对向的方式进行遍历
  2. 两个递增数组何必成一个递增数组,同向判断遍历。
    这种思想在快排与归并中都有用到。

产生随机数

在头文件cstdlib和ctime中,

首先初始化随机种子:
srand((unsigned)time(NULL));
赋值
int a = rand();
rand() 函数只能在[0,RAND_MAX]范围内的整数,RAND_MAX 是stdlib系统环境中的值。
改变rand()函数的范围
int x = rand()%(b-a+1)  范围为[0,b-a]
int x = rand()%(b-a+1)  范围为[a,b]
int x = rand()%5+3    范围为[3,7]
int x = (int)(round(1.0*rand()/RAND_MAX*50000+10000)) 范围为[10000,50000)

分数的表示

分数的定义

  1. 如果分母down为负数,那么令分子up和分母down都变成相反数。
  2. 如果分子up为0,那么分母为1
  3. 约分:求出分子绝对值与分母绝对值的最大公约数d,然后令分子分母同时除以d。

分数的四则运算:

Fraction add(Fraction f1,Fraction f2) {
    
    
	Fraction result;
	result.up = f1.up*f2.down + f2.up*f1.down;
	result.down = f1.down*f2.down;
	return reduction(result) //返回对结果分数的化简
}

注意 四则运算中,分数的乘法与除法

分数的输出

  1. 输出前,化简
  2. 如果分数r的分母down为1,说明该分数是整数
  3. 如果分数r的分子up的绝对值大于分母down,说明该分数是假分数,则整数部分r,up/r.down,分子部分为abs(r.up)%r.down,分母部分为r.down。
void showResult(Fraction r){
    
    
	r = reduction(r); //对分数的化简
	if(r.down == 1) printf("%d\n",r.up);
	else if(abs(r.up)>abs(r.down)) printf("%d %d/%d\n",r.up/r.down,abs(r.up) % r.down,r.down);
	else printf("%d/%d\n",r.up,r.down);

进制转换

使用库函数: include
using namesapce std;
bitset<8> n(变量名) 创建对象的时候可以直接传进去一个数
n(7) // 十进制转换为二进制
n(0x07) //16进制转换成二进制
n.to_string();

勉励
加油ヾ(◍°∇°◍)ノ゙
笔记是平时刷题积累的,有借鉴很多大神的,例如柳神,郝斌老师,以及算法笔记,天勤数据结构等。

如果觉得我的文章对你有所帮助与启发,点赞给我个鼓励吧(づ ̄3 ̄)づ╭❤
这篇文章会持续更新,关注我和我一起共勉加油吧!
如果文章有错误,还望不吝指教!

猜你喜欢

转载自blog.csdn.net/qq_43992949/article/details/105876021
今日推荐