奇奇怪怪的知识点/小技巧
位运算
异或
简介&简单性质
1、一个数异或自己为0,称为自反
异或的话其实可以看做不进位的加法
奇怪的用法
对于一个排列 0~ \(2^{n-1}\) 来说,我们可以找到\(2^{n-1}\)这个数并记为\(x\),让0~\(2^{n-1}-1\)的任一个数记为\(y_1\),\({y_1}\oplus{x}\)总是能得到\(y_1+x\)。让\(2^{n-1}\)+1 ~ \(2^{n-1}\)的任一个数记为\(y_2\),\({y_2}\oplus{x}\)总是能得到\(y_2-x\)。
或
我们可以用x<<1|1 来表示 \({x*2+1}\)
状态压缩
当每件事情只有01两种状态的时候,我们可以用\({2^n}\)-1来枚举各种状态,比如在使用容斥原理的时候就可以使用
数论
关于质数
2是唯一的偶质数呢,并且我们可以知道一个数x可以用1到3个质数相加得到,这分别对应着的是质数的情况,偶数以及(x-2)为一个质数的情况, 除了前两种情况的情况。
组合数
预处理
当数据范围比较小的时候,预处理组合数的值可以直接使用递推式
公式
3.20校内排位赛的H题,习得对于组合数有以下公式
字符串
构造
想要构造一个长度为d的0串并且命名为t可以直接这样写: string t(d, '0');
写法优化
scanf的特性
有些又要处理数字又要处理字符的题目,如果用scanf就可以免去处理字符类型转换到数字类型,比如说读入AM18:00,只需要
int main(){
char c1, c2, c3;
int hh, mm;
//记得getchar
int t;scanf("%d", &t);
getchar();
while(t--){
//记得在前面加空格
scanf(" %c%c%d%c%d", &c1, &c2, &hh, &c3, &mm);
printf("%c%c%d%c%d\n", c1, c2, hh, c3, mm);
}
return 0;
}
数组切段
这样就能很好地实现了,而且比较短
void check(){
_index.clear();
for(int l = 1, r = 1;l <= n;l = r+1, r = l){
while(r < n && (M[l] == M[r+1])) ++r;
_index.push_back({l, r});
}
}
匿名函数lambda
详细的介绍教程:
https://docs.microsoft.com/zh-cn/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170
这样不会破坏写程序的连贯性
sort(s+l, s+r, [](const char&A, const char&B){
return A>B;
});
int main()
{
[] {}();//三部分,[] : 代表lambda表达式的开始;{} : 代表函数体,函数体里面什么都没有;() : 代表函数调用.
}
开long long
直接这样
#define int long long;
signed main(){}
不过这样常数会很大,可能会被卡,慎重
判断
想要做到一旦有一个true它的后继状态都是true的话
(flag || (i == 1));
其中后面那个条件可以根据需求修改
换行
for(int i = 1;i <= 10;++i){
for(int j = 1;j <= 5;++j){
//这个地方是空格+\n
cout << i*j << " \n"[j==5];
}
}
杂项/debug经验
!!
vsc经常自动帮优化哇,导致oj上输出和本地输出不一样,如果有迷wa的话不妨换成cb写吧!
TLE且时间复杂度没算错
1、代码哪里写错了位置!!(有次比赛昏头了把sort写错位置了de了好久都没发现T T)
2、数组越界