1. 数字加‘0’得到对应的字符, 字符数字减‘0’可得到对应的数字
char i = 1 + '0' -> '1'
int i = '2' - '0' -> 2
2. 字符减去’A’可以得到对应的数字, 由此, A = 0, B = 1 ......
3. 正方形翻转90度可以先按对角线镜像,再垂直镜像
4. 判断闰年的代码
int leap = (year % 100 && year % 4 == 0 || year % 400 == 0) //leap为1是闰年,为0不是
// 不是100的倍数并且是4的倍数 或者 是100的倍数且也是400的倍数
5. 小学数奥知识
-
9或3的倍数,各位数字之和能被9或3整除
-
2或5的倍数,个位数字能被2,5整除
-
4的倍数,后两位能被4整除
-
8的倍数,后三位能被8整除
-
11的倍数,奇数位上数字之和与偶数位数字之和的差(以大减小)能被11或0整除
-
对于一个数ABCDEFG,如果它能被7或11或13整除,那么等价于ABCD-EFG也能被7或11或13整除(7 * 11 * 13 = 1001)
6. 转换方向技巧
在一些遍历矩阵中,可能会遇到按顺序遍历,遇到边界点需要转弯的情况,可以定义一个d变量来解决
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int d = 1; //0为上,1为右,2为下,3为左
d = (d + 1) % 4 //即转弯90°
int x = a + dx[d]
7. 下标从0开始会更方便模运算
8. n – 循环n次, – n 循环 n - 1次
9. 马走日的偏移量
int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2}; //从图中箭头所指方向开始顺时针
int dy[] = {1, 2, 2, 1, -1, -2, -2, -1};
10. 数组排序并去重*
sort(alls.begin() , alls.end());
alls.erase(unique(alls.begin() , alls.end()) , alls.end());
11. 组合数递推公式
$C_{n}^{m}$ = $C_{n - 1}^{m-1}$ + $C_{n - 1}^{m}$
解释:有n个苹果,挑一个🍎出来,分成包括那个🍎和不包括🍎的两个集合,显然,从不包含的集合中去有$C_{n- 1}^{m}$种方案,从包含的集合中取有$C_{n-1}^{m-1}$种方案
12. 判断字母的几个常用函数
if(s >= 'A' && s <= 'Z') //大写
if(s >= 'a' && s <= 'z') //小写
isupper(c); //判断是否为大写
islower(c); //判断为小写
isdigit(int c)//判断是否为数字
isalpha(int c)//判断是否为a~z A~Z
isalnum(int c)//判断是否是数字或a~z A~Z
//参数 c 表示要检测的字符或者 ASCII 码。
13. 如何定义小根堆
priority_queue<int, vector<int>, greater<int>> s;//greater表示按照递增(从小到大)的顺序插入元素
//如果堆中元素是结构体,并且要按照其中一个元素排序
struct Node{
int finish_time, cost;
bool operator< (const Node &t) const{
return finish_time > t.finish_time; //小根堆,上面小于,下面大于
}
};
14. 注释需要空两格再写(工程规范)
15. 子序列一般不连续,子串一般连续
16. 一维矩阵乘二维矩阵两重循环,二维乘二维三重循环
17. 稠密图用邻接矩阵,稀疏图用邻接表
18. memset 按字节赋值,所以memset 0x3f 就等价与赋值为0x3f3f3f3f
19.int范围内约数个数最多的数它的约数个数大约有1500个
20. 一定要用差分吗?
//c++库中有一个方法可以填充容器
fill(arr, arr + n, 要填入的内容)
21. next_permutation
函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序
例
1 0 2
1 2 0
2 0 1
2 1 0
22. 矩阵下标映射
在某些图论问题或者并查集问题中,经常会涉及到点的编号映射,也就是把二维坐标映射为一维
int get(int x, int y) // 注意这里x必须要从0开始
{
return x * n + y;
}
23. 求平面内两直线交点
$y = k_ix + b_i$
x = (b2 - b1) / (k1 - k2);
y = (k1 * b2 - k2 * b1) / (k1 - k2);
// 简化
x = (b2 - b1) / (k1 - k2);
y = x * k1 + b1;
24. 将一个数字反转接到后面
1234 -> 12344321
int y = x;
for(int i = 0; i < n; i ++) x = x * 10 + y % 10, y /= 10; // n是指数字的长度
25. 关于日期的一些事
在某些oi题中,经常会遇到一些日历题,也有一些常用的方法,鉴于本人才疏学浅,发现的方法还较少,故就不另外写一个有关的分享,如果有人知道一些常用的方法,请分享在评论区,互相学习,互相进步
- 在知道某月某日是星期几的前提下,可得出后面几个月的对应日期是星期几
//例如:在知道2021/4/2是星期五的前提下,要想知道2021/5/2是星期几,
//只需要将加上两日期相隔天数(其实就是4月份的天数),然后加上5(前提日期是星期几就加几), 然后%7即可
// 所以 (30 + 5) % 7 = 7, 所以2021/5/2是星期日
// 代码示例
days + 开始星期几 % 7 = 对应星期几 (days是指两日期相隔天数)
26. 一个字符串分隔为多行,怎么读
while(cin >> line) str += line;
27. 进制转换
char get(int x)
{
if(x < 10) return x + '0';
return x - 10 + 'A';
}
string base(int x, int b) // x是指要转换的数,b是转换为多少进制
{
string res;
while(x) res += get(x % b), x /= b;
reverse(res.begin(), res.end());
return res;
}
28. 利用stringstream读取每一行的字符
getline(cin, line);
stringstream ssin(line);
while(ssin >> a[n]) n ++;
29. 添加有权重的有向边
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
30. 所谓匹配,是要涵盖整个字符串的,而不是部分字符串
31.
LIS(Longest Common Subsequence): 最长公共子序列
LIS(Longest Increasing Subsequence):最长上升子序列
32.格雷编码
n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:
每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1)
第一个整数是 0
一个整数在序列中出现 不超过一次
每对 相邻 整数的二进制表示 恰好一位不同 ,且
第一个 和 最后一个 整数的二进制表示 恰好一位不同
通过上图的方式,可以求出下一位,也就是上一位格雷编码对称,上面补0,下面补1
6