生成随机数
加头函数
#include <cstdlib>
#include <ctime>
using namespace std;
在main函数下第一行加
srand((unsigned)time(NULL));
// 生成[a,b]
p = rand()%(b - a + 1) + a;
产生一定范围随机数的通用表示公式
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
字符串
string 操作加
#include <string>
字符数组操作加
#include <cstring>
string 转字符数组 s.c_str();
string 输入输出只能使用 cin,cout
输入一行字符串getline(cin, s);
遇到空格符,换行等停止读入 cin >> s
将数字转换成字符串注意2位数以上要多次取余转换
char 数组可以 直接赋值给string
基本类型转string 使用 to_string(int/double);
字符串相加只能一对一对加,不能2个以上一次性相加。
string s;
s += "a"; // 正确
s = s + "a" + "b"; // 错误
s.erase(index, len); 去掉的是从下标为index开始的len长度的字符,是对原字符串上操作。
编译器设置
有些编译器不支持C++11需要设置,dev设置
选择工具->编译选项->勾选
空白处添加 -std=c++11
编译器报错问题
-
C++ 遇到reference to ’ *** ’ is ambiguous 错误
定义的变量名与库函数重名,更换一下名字就好了,例如next -
在函数区定义过大数组会导致运行直接出错。将大数组定义为全局变量即可。或者在main使用vector。vector申请空间是动态申请的,在堆中,空间较大。
vector<int> v(6)
初始化为vector分配空间,可以使用&v[i] 赋值
位运算
if (x & 1)
使用&操作进行余2操作不能x & 1 == 0 因为==的优先级大于& 会先计算1 == 0,为false 导致x&false 始终为false了。
stl
可以使用auto遍历容器的元素,类似于java的增强for循环。
vector添加结构体可以使用{x,y}来表示。
#include <bits/stdc++.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Node{
int x, y;
};
int main(int argc, char** argv) {
vector<Node> v;
v.push_back({1,2});
for (auto it: v) {
printf("%d %d", it.x, it.y);
}
return 0;
}
c++11的auto遍历map
for(auto it: mp) {
cout << it.first << it.second;
}
优先队列排序priority_queue需要重载结构体的<号
struct Node{
int x, y;
friend bool operator < (Node n1, Node n2) {
return n1.y < n2.y;
}
};
这样使得大的在顶部。
list的内置sort对结构体排序也需要重载结构体的<号
struct Node{
int x, y;
friend bool operator < (Node n1, Node n2) {
return n1.y < n2.y;
}
};
跟优先队列的相反,这样表示从小到大排列
bitset
常用于判断数组哪一位取不取。集合合并,统计N个数组成的不同数的个数。
bitset<n> bs; // 如集合bs 存放 10110110
bs = bs | bs << n; //表示原集合bs和集合bs内所有1左移n位, 原来位置上的1就到了1+n位上
// 如左移2位 bs << 2, bs就变成 00101101,i位置上为1左移n位相当于i+n位置变成1
// 在和bs进行或操作, bs = 10111111
int x = bs.count(); // 统计bs集合中1的个数
进制转换
负进制转换
若余数为负,商 = 商+1,余数= 余数 - 除数
-15 = -2 * 7 …-1
余数 = -1 - (-2) = 1
商等于 7 + 1 = 8
8 = -2 * 4 … 0
…
-15 = 110001(-2) = =1×(−2)^5 +1×(−2)^4 +0×(−2)^3 +0×(−2)^2 +0×(−2)^1+1×(−2)^0
库函数使用
lower_bound
非递减数组二分查找,即升序,存在重复的元素
lower_bound 查找第一个大于等于x的数,返回的是数组对应的下标地址指针。需要减去数组初始地址得到整数坐标,下面同理。
upper_bound 查找第一个大于x的数,返回的是数组对应的下标地址指针。
int v[20];
int p = lower_bound(v, v + n, x) - v
int p = upper_bound(v, v + n, x) - v
非递增数组二分查找,即降序,存在重复的元素
重载lower_bound 查找第一个小于等于x的数,返回的是数组对应的下标地址指针。
重载upper_bound 查找第一个小于x的数,返回的是数组对应的下标地址指针。
int p = lower_bound(v, v + n, x, greater<int>()) - v;
int p = upper_bound(v, v + n, x, greater<int>()) - v;
代码实现二分查找
__builtin_popcount(x)
统计x的二进制中1的个数,O(M)的时间复杂度,M为1的个数。
实现:
利用n&(n-1)使得n的二进制末尾最后一个1变0.
n = 01010100
n-1 = 01010011
所以每次的与操作将n的末尾1变0,其他位不变,直到n变为0结束。
int hammingWeight(uint32_t n) {
int cnt = 0;
while (n) {
cnt++;
n &= (n - 1);
}
return cnt;
}
取余
一个数的前i位对n取余之后的结果在连接上第i+1位在对n取余等于前i+1位为n取余的结果。
如:314
31 % 3 = 1—连接上4----> 14 % 3 = 2
314 % 3 = 2
即如果判断一个很长的整数是否能被n整除,可以从高位一位一位取余在连接后一位判断。