一些常用用法记录

该篇笔记整理C++的一些常用用法和技巧等等,方便查看。

包括所有的资料整理都在最后,统一在这一个文档方便查看。

C++中将字符转换为整数、整数转为字符

将单个字符进行转换,可以直接使用类型转换,或者使用ascii码

如下所示:

int main()
{
    char c = '1';
    int a = (int) c;
    int b = c - 48; # '0'的ascii码为48
    int b = c - '0'; 
}

将数字转为字符可以用char,例如(char)(1 + 'A')

C++ 中将字符串转换为整数

C++是一种强类型语言,不能直接使用类型转换将字符串转为数字,例如下面的方式就会报错:

int main()
{
    string str = "7";
    int num;
    num = (int) str;
}

如果是一个字母字符例如’A’,则转为数字为 ch - 'A' + 10;

使用stoi()函数

接收一个字符串作为输入,并返回其整数版本作为输出

例如:

int main()
{
    string str = "7";
    int num = stoi(str);
    cout << num << endl; # 7
}

最小公倍数、最大公因数、互质判断

最小公倍数是数论中的一个概念,在所有正的公倍数中,最小的公倍数就叫最小公倍数。lcm是英语last common multiple的首字母缩写。

两个整数的lcm与最大公因数之间的关系为:

l c m ( a , b ) = ∣ a b ∣ g c d ( a , b ) lcm(a,b) = \frac{|a b|}{gcd(a,b)} lcm(a,b)=gcd(a,b)ab

最大公因数(highest common factor)可以利用短除法得到,也称最大公约数,greatest common divisor,gcd。指能够整除多个整数的最大正整数。

求取两个整数最大公约数的方法:

  • 列举法,
  • 素因数分解,
  • 短除法:两数除以其共同素因数,直到两数互素,所有除数的乘积即为最大公约数。

使用短除法,辗转相除法进行代码实现:gcd(a,b) = gcd(b, a%b),不断地用大数除小数,直到除后的余数为0,此时另一个数就是最大公因数。

int gcd(int x, int y){
    int z = y;
    while(x%y){
        z = x%y;
        x = y;
        y = z;
    }
    return z;
}

或者:

int gcd(int a, int b){
    while (a&&b){
        if (a>b) a%=b;
        else b%=a;
    }
    return a + b;
}

使用三元运算符进一步简化:

int gcd(int a, int b){
    while(a && b && (a > b ? a%=b : b%=a));
    return a+b;
}

然后就可以利用最大公约数求出最小公倍数

int lcm(a, b){
    return a/gcd(a,b) *b;
}

也可以利用最大公约数判断两个整数是否互质,只需判断他们的gcd是否为1,为1则是互质的。

或者使用STL内置函数__gcd(x,y)求gcd。包含在头文件#include<algorithm>

c++中统计字符串中某个字符出现的次数

可以使用count方法

int main()
{
    string s = "ababc";
    int num = count(s.begin(), s.end(), 'a');
}

c++中创建键值对类型

例如题目:大石头的搬运工

对于键值对类型数据,键可能有重复的,可以直接创建pair类进行模拟,还方便使用。注意这些技巧的运用。

一维前缀和、二维前缀和

一维前缀和:

prefix[i] = prefix[i-1] + a[i];
// 求某个区间的和
prefix[r] - prefix[l-1];
// 恢复
a[i] = prefix[i] - prefix[i-1];

二维前缀和:

pre[i][j] = pre[i][j-1] + pre[i-1][j] -pre[i-1][j-1] + pre[i][j];

// 求某个区间和

一维差分、二维差分

一维的差分:

diff[i] = a[i] - a[i-1];

// 区间操作
diff[l] += c;
diff[r+1] -= c;

// 求原数组
a[i] = a[i-1] + diff[i];

二维的差分:

s[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1];

// 区间操作
s[x1][y1] += c;
s[x1][y2+1] -= c;
s[x2+1][y1] -= c;
s[x2+1][y2+1] += c;

// 恢复
a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + s[i][j];

C++输入二维矩阵

  • 使用for循环嵌套输入二维矩阵
int mx[3][3];
// 输入
for (int i = 0; i < 3; ++i){
    for (int j = 0; j < 3; ++j){
        cin >> mx[i][j];
    }
}

// 使用for 循环进行输出
for (int i = 0; i < 3; ++i){
    for (int j = 0; j < 3; ++j){
        cout << mx[i][j] << " ";
    }
}
cout << endl;
  • 使用指针输入二维矩阵
int **mx; // 定义指针矩阵
// 分配内存
mx = new int *[3];
for (int i = 0; i < 3; ++i){
    mx[i] = new int [3];
}

// 输入
for (int i = 0; i < 3; ++i){
    for (int j = 0; j < 3; ++j){
        cin >> *(*(mx + i) + j);
    }
}
// 输出
for (int i = 0; i < 3; ++i){
    for (int j = 0; j < 3; ++j){
        cout << *(*(mx + i) + j) << " ";
    }
    cout << endl;
}
// 释放内存
for (int i = 0; i < 3; ++i){
    delete[] mx[i];
}
delete[] mx;

C++中数组求和

使用C++中的numeric库执行数值操作,、

假设一个数组,可以使用accumulate(param1, param2, 0)求和。

例如:

#include <iostream>
#include <numeric>
using namespace std;

int main()
{
	int a[10];
	int n = 5;
	for (int i = 0; i < n; ++i) cin >> a[i];
	int sum = accumulate(a, a+n, 0);
	cout << sum << endl;
	return 0;
}

当然也可以直接遍历求和。

C++中求最值

max()和min()只能对两个元素求最值?是吗

如果对数组求最值可以使用max_element()或者min_element,注意这两个函数返回的是位置指针,所以要得到值可以用*max_element(a+1, a + 1 +n)。

C++中求区间最值

了解ST表,利用倍增和动态规划的思想实现求区间最值,

在第7章基础数据结构有介绍到,

单调队列求区间最值

给定区间长度求滑动区间的最值,可以理解为滑动窗口最大值算法,

C++优先队列

常用用法:

  • pq.pop()
  • pq.push()
  • pq.top()
  • pq.empty()
  • pq.size()

默认排序大小,从大到小

priority_queue<int> pq;

pq.push(x);

如果小顶堆,则为

priority_queue<int, vector<int>, greater<int>> pq;

C++中对字符串的操作

对字符串排序

例如:

string s;
cin >> s;
sort(s.begin(), s.end());  // 这样即可

提取子串

例如:

string s; cin >> s;
s2 = s.substr(3,4); // 两个参数,第一个位置起始位置,第二个为长度

C++中lower_bound()和upper_bound()

两个都是利用二分查找的方法在一个排好序的数组中进行查找的。

lower_bound(begin(), end(), num),查找第一个大于或等于num的数字,并返回地址,不存在则返回end

upper_bound()查找第一个大于num的数字

在从大到小的数组中,重载lower_bound()和upper_bound()

lower_bound(begin(), end(), greater<type>()),二分查找第一个小于或等于num的数字

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000+10;
const int INF = 2*int(1e9) + 10;
#define LL long long

int cmd(int a, int b){
    return a > b;
}

int main()
{
    int num[6] = {1, 2, 4, 8, 21, 92};
    sort(num, num + 6);
    int pos1 = lower_bound(num, num+6, 8) - num;
    int pos2 = upper_bound(num, num + 6, 8) - num;
    cout << pos1 << " " << num[pos1] << '\n';
    cout << pos2 << " " << num[pos2] << '\n';
    

    return 0;
    
}

C++中向上取整、向下取整、四舍五入的小技巧

向上取整,可以用函数ceil(),还有一种方法就是,假如要对a/b向上取整,例如acwing中的例题“小苹果”,则向上取整的结果是(a+b-1)/b

向下取整,可以用函数floor(),还有一种方法就是,假如要对a/b向下取整,则为a/b

小数点四舍五入得到整数,可以用(a+b/2)/b,或者round(a/b)

但是如果保留几位小数则需要以下方法,例如保留2位小数:

float a = 2.3678;
    cout << round(a*100) / 100 << endl;
    cout << floor(a*100 + 0.5) / 100 << endl;

C++中整除的性质

整除了解即余数为0.

掌握k进制转10进制,10进制转k进制

C++中memset函数用法

memset,char型初始化函数

头文件:<string.h> 或<memory.h>

函数原型:

void *memset(void *s, int chm size_t n)

memset(结构体/数组名, 用于替换的ASCII码, 前n个字符)

memset(结构体/数组名, 用于替换的字符, 前n个字符)

将s中的前n个字节用ch替换并返回s

常用于较大的对结构体和数组的清零操作。

可用于将数组初始化为0或-1.

例如:

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    int a[10];
    memset(a, 0, sizeof(a));
    for (int i = 0; i < 10; ++i)cout << a[i] << " ";
    cout << endl;
    memset(a, -1, sizeof(a));
    for (int i = 0; i < 10; ++i) cout << a[i] << " ";
    return 0;
}

输出

0 0 0 0 0 0 0 0 0 0 
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Pair用法、在vector中使用Pair

pair组合两个数据,可以是不同类型。

例如STL中的map就是将key和value组合在一起。

或者当某个函数需要返回2个数据的时候,可以选择pair。

pair的实现是一个结构体,访问方式是.first和.second。

头文件#include< utilit >

下面是示例:

pair<T1, T2> p1; // 空的pair对象
pair<T1, T2> p1(v1, v2);
make_pair(v1, v2); // 创建一个新的pair对象
p1 < p2; // 按照字典序比较
pair<string, vector<int>> line; // 两个对象不必相同

使用vector存储pari数据类型

vector<pair<int, string>> myVector; 
myVector.push_back(make_pair(1, "Hello"));
for (auto & item : myVector){
    cout << item.fisrt << " " << item.second << endl;
}
#include <bits/stdc++.h>
using namespace std;

vector<pair<int, int> > ab;

int main()
{
	int n; cin >> n;
	int cnt = n/10;
	for (int i = 0; i < n; ++i){
		int a, b;
		cin >> a >> b;
		ab.push_back(make_pair(a, b));
	}
	for (auto & item : ab){
		cout << item.first << " " << item.second << endl;
	}
	
	return 0;
}

1-N中与N互质的个数有一个公式:欧拉函数模板

例题:蓝桥杯互质数的个数、acwing欧拉函数

https://www.acwing.com/solution/content/81875/

https://www.lanqiao.cn/problems/4330/learning/?page=1&first_category_id=1&name=%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n; 
    cin >> n;
    while (n--){
        int a; 
        cin >> a;
        int res = a;
        // 分解质因数
        for (int i = 2; i <= a/i; ++i){
            if (a%i == 0){
                // res = res *(1 - 1/i);
                res = res / i *(i-1);
                while (a % i == 0) a /= i;
            }
        }
        if ( a > 1) res = res / a *(a - 1);
        cout << res << endl;
    }
    
    return 0;
}

vector,list, map, set的反向遍历技巧

https://articles.oyoung.cc/2020/09/24/C-%E5%B0%8F%E6%8A%80%E5%B7%A7-%E9%9B%86%E5%90%88-vector-list-map-set-%E7%9A%84%E5%8F%8D%E5%90%91%E9%81%8D%E5%8E%86/

可以多看看acwing上的帖子,https://www.acwing.com/blog/content/32956/

C++中优先队列的实现

参考:https://blog.csdn.net/weixin_57761086/article/details/126802156?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170869912916800188573407%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=170869912916800188573407&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-126802156-null-null.142v99pc_search_result_base6&utm_term=c%2B%2B%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97&spm=1018.2226.3001.4187

优先队列默认是大堆。

声明:

template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type>>

  • T 存储元素的类型
  • 第二个是底层使用的存储结构,默认使用vector
  • 第三个是优先队列中元素比较方式的类
// 简化版创建默认大堆
priority_queue<int> q;

// 完整版
priority_queue<int, vector<int>, less<int>> q;

// 创建小堆
priority_queue<int, vector<int>, greater<int>> q;

C++中vector容器的排序或者数组的排序

从小到大:sort(arr.begin(), arr.end())

从大到小:

  • sort<arr.begin(), arr.end(), greater<int>()>
  • 使用自定义函数
bool cmp_max(int x, int y){
	return x > y;
}

sort(arr.begin(), arr.end(), cmp_max);

当然了这里cmp_max的写法也可以这样写:

sort(arr.begin(), arr.end(), [&](int x, int y){
    return x > y;
}
  • 先sort(),再reverse()
sort(arr.begin(), arr.end());
reverse(arr.begin(), arr.end());

数组的排序:

int a[10];
sort(a+1, a+a.size());

C++中vector容器删除元素

示例:

vector<int> v = {1, 2, 3, 4, 5, 6};
v.erase(v.begin() + 2);

C++中数组或者vector获取最大值、最小值以及索引

示例:

#include <bits/stdc++.h>
using namespace std;

int main()
{
	// 数组获取
	int arr[6] = {1, 2, 3, 4, 5, 6};
	int maxValue = *max_element(arr, arr+sizeof(arr)/sizeof(int));
	int minValue = *min_element(arr, arr+sizeof(arr)/sizeof(int));
	int maxPosition = max_element(arr, arr+6) - arr;
	int minPosition = min_element(arr, arr+6) - arr;
	cout << "maxValue: " << maxValue << endl;
	cout << "minValue: " << minValue << endl;
	cout << "maxPosition: " << maxPosition << endl;
	cout << "minPosition: " << minPosition << endl;
	
	// vector获取
	vector<int> arr1{1,2,3,4,5,6};
	int maxValue1 = *max_element(arr1.begin(), arr1.end());
	int minValue1 = *min_element(arr1.begin(), arr1.end());
	int maxPosition1 = max_element(arr1.begin(), arr1.end()) - arr1.begin();
	int minPosition1 = min_element(arr1.begin(), arr1.end()) - arr1.begin();
	cout << "maxValue1: " << maxValue1 << endl;
	cout << "minValue1: " << minValue1 << endl;
	cout << "maxPosition1: " << maxPosition1 << endl;
	cout << "minPosition1: " << minPosition1 << endl;
}

C和C++中int a;默认值为多少

C语言中定义int变量,全局变量即定义在函数外的变量,默认为0;

静态局部变量默认为0;

C++也是。

欧拉函数模板

4330欧拉函模板,

#include<bits/stdc++.h>
using namespace std;


int main()
{
	int a; cin >> a;
	int res = a;
	// 分解质因数
	for (int i = 2; i <= a/i; ++i){
		if(a%i == 0){
			res = res / i * (i -1);
			while(a%i == 0) a /= i;
		}
	} 
	if (a > 1) res = res / a*(a - 1);
	cout << res << endl;
	
	return 0;
}

快速幂模板

LL ksm(LL a, LL b){
	LL res = 1;
	while(b){
		if (b & 1) res = res*a % MOD;
		a = a*a%MOD;
		b>>=1;
	}
	return res;
}

C++中求log对数运算

默认的log函数,

#include <iostream>
#include <cmath>
using namespace std;

int main(){
	double a = 9, b = 10;
	cout << log(a) << endl; // log默认以e为底 
	cout << log(exp(a)) << endl; 
	cout << log10(b) << endl; // 以10为底 
	
	return 0;
}

自定义m为底, 求logm(n)的值,可以如下:求以2为底可以用到

double a = log(n)/ log(m);

C++中的绝对值

不同类型使用不同的绝对值函数,

int abs(int i); // 整型

double cabs(struct complex znum); // 复数的绝对值

double fabs(double x); // 双精度的绝对值

long labs(long n); // 长整型的绝对值

C++中对字符串求长度、截取字符串

可以使用三种范式:

string strTest = "test";
// 第一种
strTest.length();
// 第二种
strTest.size();
// 第三种,转换为c风格字符串
strlen(strTest.c_str());

https://blog.csdn.net/ezhou_liukai/article/details/13779091

c++STL中Map的按Key排序和按Value排序

map内部本身就是按序存储的,例如红黑树,插入数据时会按照key的大小顺序进行存储。

插入数据可以如下:

map<int, int> mymap;
mymap[0] = 0; // 方式1
mymap.insert(make_pair(1,1)); // 方式2

使用.count(key)查看是否存在key

使用.keys获取所有的key

使用.first和.second访问键值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值