- 同一个程序不同时使用cout、printf,否则有时会出错,不推荐用cin cout
- ”\n”比endl快
- long long(-922*10^16——922*10^16)赋初值大于2^31-1(2e9)时,初值后要加LL,否则会编译错误···9e18
- Int(-21*10^8——21*10^8)···2e9
- 1MB可以存262144大的数字数组(1*1024*1024*8/32=262144)
- %f是float和double的输出格式
- 浮点型都用double
- 小写字母-大写字母 = 32
- c语言中没有可以存储字符串的基本数据类型(c++有string类型),只能用字符数组的方式
- 字符串常量可作为初值赋给字符数组:char c[5] = “1 34”,但不能赋给字符变量
- 强制类型转换:(新类型名)变量名,(int)不会四舍五入,直接去除小数
- 给多个变量赋同一个值,可用连续等号:a = b = 3
- n /= m + 1 等价于 n = n/(m + 1)
- scanf %c(读入字符变量)可以读入空格与换行,%s(读入字符数组)不能(它以空格、换行为读入结束标志)
- %md:不足m位以m位右对齐输出,高位用空格补齐,多于m位保持原样输出;
- %0md:与上不同在于用0补齐
- %.mf:保留m位小数输出,四舍五入
- getchar()输入单个字符,可以识别换行符(读入换行符),c1 = getchar();接受并存于c1,getchar();接受但不存储;putchar()输出单个字符,putchar(c1);输出字符c1
- gets();输入一行字符串并存于字符数组中,(识别换行符\n作为输入结束):char str[5];gets(str); puts();输出一行字符串,并紧跟一个换行put(str);
- typedef给复杂数据类型取别名,typedef long long LL;
- define 定义末尾不用加;
- const 定义常数 const int a = 3;
- math.c常用函数:
- fabs(double x); 取绝对值
- floor(double x); 向下取整,ceil(double x);向上取整
- pow(double r,double p); r^p
- sqrt(double x); 根号x
- log(double x); lnx
- sin(double x);cos(double x);tan(double x); 弧度制三角函数
- asin(double x);acos(double x);atan(double x); 弧度制反三角函数
- round(double x); 四舍五入,返回double,强制取整后为四舍五入
- 以上均返回double型
- c语言不允许在for循环第一句定义变量,但c++允许
- 数组大小必须是整数常量,不能是变量
- 数组大小较大(10^6级别),需在主函数外定义
- memset( a , 0/-1/127 , sizeof(a) ); //给数组a[n]全赋0/-1/INF(2139062143) 头文件cstring
- 字符数组末尾会有\0,占用一个char,所以定义字符数组长度时要比实际用到的长度大1
- scanf的%s格式与gets读取字符串时会末尾自动加\0,若不是用这两种方式读入字符串,则需要在最后再读入’\0’,否则printf或puts因无法读到\0而无法确定结尾,而在末尾输出乱码
- string.h:
- strlen(str) 返回第一个\0前得到字符个数
- strcmp(str1,str2) 返回两个字符串大小比较结果,<:负整数 =:0 >:正整数
- strcpy(str1,str2) 将str2复制给str1(包括\0),会将st1原有覆盖
- strcat(str1,str2) 将str2接到str1后
- (在stdio.h中) sscanf(str,”%d”,&n)将字符数组str的内容以%d格式写到n中(从左到右),sprintf(str,”%d”,n)将n以%d的格式写到str字符数组中(从右到左)
- 数组作为函数参数:一维数组不用在[]内写大小,二维第一维不用,第二维需要,数组作为参数时,函数对数组元素的修改就等同于对原数组元素的修改(与普通局部变量不同),但不允许作为返回类型
- 指针:以下均举int型为例子:
- 变量的地址一般指它占用的第一个字节的地址
- 获得变量的地址,只需在变量前面加&:a,&a
- 指针变量存放指针,指针指向地址(可将指针就理解为地址)(unsigned类型的整数)
- 定义指针变量:在某种数据类型后加*,同时定义多个不能int* a,b,c(这样只有a是int*型,bc为int型) 应该int* a,*b,*c; int*为指针变量的类型,后面的a、b、c才是变量名
- 给指针变量赋值,先把某变量的地址取出,再赋给指针变量:int *p=&d;或int *p;p=&d;
- 已有一地址(指针变量),获得地址上的值,只需再地址前加*:*p==d
- 对*p赋值,相当于通过d的地址对d赋值(或改变值)
- 指针变量作为函数参数,函数定义时,void f(int* p)此时其形参为指针类型,故在传入实参时,传入的是指针变量(p,而不是*p)(即地址),函数内的操作,应用*p,这样才是对p所指变量的操作,否则用p则是对地址的操作(且像普通变量一样无法传递到函数外的地址),f函数内对*p的操作,会传递到p所指的变量上: void f(int* p){ *p = 123 } int main(){ int a; int* p=&a; f(p); }
- C++中的引用&也可以实现自定义函数内操作影响到函数外,但引用&不是取地址
- 对指针变量加减法,相当于地址偏移的距离,p+1指p所指的int型变量的下一个int型变量地址,两int地址相减,用%d输出,为两地址之间相差的int的数量,而不是字节差的值
- 对数组,&a[0]==a,为a[0]的地址(也为数组首地址), &a[3]为a[3]的地址,a+i是a[i]的地址,即*(a+3)==a[3]
- 结构体struct:
- 定义:struct student{ //一些基本或自定义数据类型}; students Alice; student stu[10](}需有;) 也可struct student{ }Alice,Bod,stu[10];(Alice Bod为两个结构体变量(student),stu[1000]为结构体数组)
- 访问结构体内元素:“.”/“->”
- struct student{ int id; student *next;}stu,*p;(定义了指针next指向下一个student(结构体),定义了普通变量stu(结构体),指针变量p),可:stu.id、(*p).id、p->id
- 有关构造函数。。。
- getline()读入一整行:
- Char str[100]; cin.getline(str,100); 将一整行都读入字符数组str中
- String str; getline(cin,str); 将一整行都读入string容器str中
- OJ系统一秒能运算的次数为:10^7——10^8
- char类型全局变量初始化值为 ‘\0’
- ?????计算程序运行时间(包括I/O(输入输出)的时间):
- freopen(filename,mode,stream) 重定向标准输入输出流,头文件#include<stdio.h> eg: freopen( “D:\\a\\tset.in” , ”r” , stdin);
freopen( “D:\\a\\test.out” , “w” , stdout);
***
fclose(stdin);
fclose(stdout); - 浮点数比较(精度问题),浮点数在存储中不总是精确,需要带入一个极小值(10^-8)来辅助比较(没经过容易损失精度的比较可以直接比较):
不必死记硬背,理解:
const double eps = 1e-8;
const double Pi = acos(-1.0); //Π的精确值
#define Equ(a,b) ( ( fabs ( (a) - (b) ) ) < (eqs) ) // == 不等于则变( !Equ(a,b) )
#define More(a,b) ( ( (a) - (b) ) > (eqs) ) // >
#define Less(a,b) ( ( (a) - (b) ) < (eqs) ) // <
#define MoreEqu(a,b) ( ( (a) - (b) ) > (eqs) ) // >=
#define LessEqu(a,b) ( ( (a) - (b) ) < (eqs) ) //<= - scanf返回值为成功读入的参数个数,读取文件时到达文件末尾会导致读入失败,返回-1(c语言用EOF代表),当题目未说明有多少数据输入时,可根据scanf(“%d”,%n) != EOF判断。在黑框输入数据时,不会触发EOF状态,但可以按<Ctrl+Z>(显示^Z),再按<Enter>,就可以触发。若为gets(str),其返回str地址,可通过gets(str) != NULL判断输入结束。
- 用字符绘图形:直接输出、用二维数组输出
- 进制转换,可将十进制作为跳板
- 时刻注意是否会爆int等
- 1e-5 == 10^(-5)
- a&b 二进制对齐,按位进行与计算(只有11才得1)
- a|b 二进制对齐,按位进行或计算(只有00才得0)
- a^b 二进制对齐,按位进行异或计算(异1同0)
- If(b%2 == 1) 用 if(b&1)替代(后者更快,以下同理)
- If(a != b) 用if( a & b )替代
- b/2 用b >> 1替代,b*2用b << 1替代
- 生成随机数:int main(){
srand((unsigned)time(NULL));
int a = rand();//范围在[0 - RAND_MAX]RAND_MAX一般为32767以上
}//需要stdlib.h与time.h头文件
想要输出给定[a,b]范围内的,则rand()%(b-a+1)+a
srand(time(NULL));只需要执行一次即可。 - 格式错误可能空格导致,可用#代替空格检查
- 字符变数字:c1 - ‘0’;
- 1既不是素数,也不是合数
- #include<vector> 向量(变长数组)
- vector<typename> name; typename == int double char struct STL容器等(为容器时,>>之间加空格) eg: vector<vector<int> > vi; vector<int> vi[100]也行,但一维长度固定
- 首元素地址 vi.begin() 尾元素地址的下一个地址 vi.end()(不存任何元素) 第n个元素地址 vi.begin()+n-1 第n个元素:*(vi.begin() + n-1)(STL容器中只有vector与string能使用迭代器与整数加法)
- 下标访问:vi[index];
- 迭代器iterator访问:类似指针,定义迭代器:vector<typename>::iterator it;{
eg:vector<int> vi; vector<int>::iterator it = vi.begin(); *(it + n) // vi[n]; - vi.size(); 获取元素个数 O(1)
- vi.push_back(x); 在vector末尾添加x O(1)
- vi.pop_back(); 删除尾元素 O(1)
- vi.clear(); 清空所有元素 O(n)
- vi.insert(it,x); 在迭代器it处插入x O(n)
- vi.erase(it); 删除迭代器it处的元素 vi.erase(it1,it2) 删除迭代器[it1,it2)区间元素 均为O(n)
- vector<int> abc(10); //初始化了10个默认值为0的元素
vector<int> cde(10, 1); //初始化了10个值为1的元素
//通过数组地址初始化
int a[5] = { 1,2,3,4,5 };
//通过数组a的地址初始化,注意地址是从0到5(左闭右开区间)
vector<int> b(a, a + 5);
- #include<set> 集合(内部有序 元素不重复)
- set<typename> name; type其他与vector一样
- set<typename> st[100]; set数组
- 只能迭代器访问元素
- set<typename>::iterator it; set迭代器,不支持it+n,it>st.begin()/< , 支持=、!=
- set内元素自动递增排序,自动去除重复数组
- st.size(); 获取元素个数 O(1)
- st.insert(x); 将x插入set中 O(log n)
- st.find(x); 返回set中值=x的迭代器 O(log n)
- st.clear(); 清空set O(n)
- st.erase(it); 删除迭代器为it的元素 O(1) st.erase(it1,it2) 删除迭代器[it1,it2)区间的元素 O(it1-it2)
- #<string> //与#<string.h>不是一个头文件
- string str;
- 下标访问:str[index]
- 读入输出只能用cin、cout
- str.c_str(); 返回对应的字符数组
- string::iterator it; it = str.begin(); *(it+n) == str[n];
- str3 = str1+str2 拼接str1与str2并赋给str3
- 支持== != < <= > >=进行比较,规则为字典序
- str.lenth()/str.size() 返回长度 O(1)
- str.insert(pos,str1) 在pos处插入str1,eg: str.insert(3,str1),在str[3]处插入 O(n)
- str.clear() 清空str O(1)
- str.substr(pos,len) 返回从pos开始,长度为len的字串 O(len)
- str.find(str1) 当str1是str字子串时,返回第一次出现位置,不是子串返回string::npos(一个常数,本身为1,但为unsigned_int型,故也可认为是unsigned_int型的最大值,作为find函数失配时的返回值,可认为等于-1或4294967295) str.find(str1,pos) 从pos位开始匹配str1,返回值与上相同
- str.replace(pos,len,str1) 把str从pos位开始、长度len的子串替换为str1
str.replace(it1,it2,str1) 把str的迭代器[it1,it2)范围的子串替换为str1 - str.erase(it) str.erase(it1,it2) 与vector、set相同 O(n)
- #include<map> //将任何基本类型映射到任何基本类型(包括STl),一一映射
- map<typename1,typename2> mp; //1型映射到2型
- map<char,int> mp //mp[‘a’] = 1,字符到整数的映射
- map<string,int> mp //mp[“abc”] = 1,字符串到整数的映射,不能用char[]
- map<set<int>,string> //setSTL到字符串的映射
- 下标访问,如上
- 迭代器访问:map<typename1,typename2>::iterator it; it = mp.begin();
it->first 当前映射的键,it->second 当前映射的值 (it++进行下一个) - map会将键从小到大自动排序
- find(key) //返回键为key的映射的迭代器,O(logN),N为映射个数
- erase()
- erase(it) //it为需要删除的映射的迭代器,O(1)
- erase(key) //key为需要删除的映射的键,O(logN)
- erase(first,last) //first,last为迭代器,删除区间[first,last),O(last-first)
- size() //获得映射的对数,O(1)
- clear() //清空所有映射,O(N)
- map<typename1,typename2> mp; //1型映射到2型
- #include<queue> //队列,先进先出
- queue<typename> q; //typename可为任意基本数据类型和STl
- 只能通过q.front()访问队首,q.back()访问队尾,且使用前必须empty()判断
- push(x) //令x入队,O(1)
- pop() //令队首元素出队,O(1)
- empty() //检查queue是否为空,空返回ture,非空返回false,O(1)
- size() //返回queue中元素的个数,O(1)
- #include<stack> //栈
- stack<typename> name;
- X.top() //获取栈顶元素,只能通过此来访问栈顶元素 O(1)
- X.push(a) //将a入栈 O(1)
- X.pop() //弹出栈顶元素 O(1)
- X.empty() //返回ture为空,返回false为非空 O(1)
- X.size() //返回元素个数 O(1)
- #include<utility> //#include<map>包括了utility,有map时不用utility
- 绑定两个元素 //类型可不同,例如下
- pair<string,int> p; //定义时初始化,pair<string,int> p(“abc”,3);
- 访问:p->first,p->second;
- 可用== != < <= > >=比较,先比较first,(若相等)再比较second;如:p1>p2
- #<algorithm>
- max(x,y) min(x,y) //参数只能2个,可以是浮点数
- abs(x) //返回绝对值,x必须是整数,浮点数使用math的fabs
- swap(x,y) //交换
- reverse(it1,it2) //将指针或迭代器在[it1,it2)之间的元素反转
- next_permutation(a,a+n) //使a[n]序列变为其下一个全排列,到最后一个时返回false
- fill(a,a+n,num) //对数组或容器某一段区间赋相同值,a[0]~a[4]:(a,a+5)
- sort(a,a+n) sort(a,a+n,cmp) //对区间排序,默认递增
- lower_bound(first,last,val) //用在有序数组或容器中,返回[first,last)中第一个大于等于val的元素的位置(指针/迭代器),若没有找到,则返回可以插入val的位置(即假设存在该元素时,其位置),若取下标,返回值-首元素地址
- upper_bound(first,last,val) //与上同理,区别为返回第一个大于val的元素的位置
- 快读
- O2优化
- static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。