这次是我第一次参加比赛,也是第一次见到大佬的学习状态,果然成功的人背后的坚辛是难以预测的,我把学长讲的东西大概总结了一下,据说比赛可以带纸质的参考资料,嘿嘿嘿。
#include<iostream>
#include<cstring>#include<string>
#include<cmath>
#include<cstdio>
#include<map>
#include<set>
#include<algorithm>
#include<iomanip>
#include<sstream>
using namespace std;
int main()
{
return 0;
}
//用到的函数
一、string
1、erase函数删掉指定位置字符
(1)string& erase ( size_t pos = 0, size_t n = npos );
(2)iterator erase ( iterator position );
(3)iterator erase ( iterator first, iterator last );
也就是说有三种用法:
(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)
2、截取子串
s.substr(pos, n) 截取s中从pos开始(包括0)的n个字符的子串,并返回
3、resize(int n,char c)函数
表示调整容器的大小为n,扩容后的每个元素的值为c,默认为0
resize()会改变容器的容量和当前元素个数,如果长于规定的值,则裁掉多余的部分
4、replace
(1)、replace(int i,int num,string s)从第i个位置以后的num个字符替换为s
(2)、replace(int a,int num1,string s,int b,int num2)从第a个位置以后的num1个字符替换为s中第b个位置以后的num2的字符
PS:s.replace(0,0,s1):在s之前插入s1
s = "asd";
s1 = "123";
s.replace(0,0,s1);
输出s运行:123asd
5、find
(1)、s.find(string s1);返回s1在s中第一次出现的下标位置
string s = "123456123456";
string s1 = "123";
int a = s.find(s1);
cout<<a<<endl;
运行结果:a = 0;
(2)、s.find(string s1,int num):从下标num开始查找s1返回在s中的下标位置
string s = "123456123456";
string s1 = "123";
int a = s.find(s1,5);
cout<<a<<endl;
运行结果:a = 6;
6、char转string
char str[10];
string s(str);//或者是s = str;
7、string转char
const char *str;
string s;
str = s.c_str();
二、四舍五入
double a = 11/2.0;
int b = (int)(a+0.5);
三、控制位数
double fixed<<setprecision(num)(#include<iomanip>)
四、输入输出
1、scanf和string:
string a;
a.resize(100); //需要预先分配空间
scanf("%s", &a[0]);
puts(a.c_str());
2、printf和string:
string s = "中国";
printf("%s" , s.c_str());
3、据说面对大量数据时printf、scanf能节省时间
4、常用
scanf("%d",&int);
scanf("%lf",&double);
scanf("%f",&float);
scanf("%c",&char);
scanf("%s",&char *);//不读取空格,gets(char *)读取空格
printf("%m.nf",**):输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。
printf("%-m.nf",**):输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。
五、读取输入的空格
cin.get()
六、字符转换数字
‘0’ - 48 = 0;
七、大写小写字母
小写-32=大写
八、string转为int int转为string
int Si(string a)
{
stringstream s;
s.str(a);
int c;
s>>c;
return c;
}
string Is(int a)
{
stringstream s;
s<<a;
string ss = s.str();
return ss;
}
九、判断素数
bool judge(long long int num)
{
if(num==1)//注意1 的情况
return false;
long long n = sqrt(num);
for(long long int i=2;i<=n;i++)
if(num%i==0)
return false;
return true;
}
十、memset()函数
memset(dp,0,sizeof(dp)); 赋值0;
memset(dp,-1,sizeof(dp)); 赋值-1
memset(dp,127,sizeof(dp)); 赋值很大的数
memset(dp,128,sizeof(dp));赋值很小的数
十一、填充字符串
1、cout<<setw(n)<<setfill(cc)<<ccc;字符串以长度n输出,不足n前面填充字符cc
2、
cout<<ccc;
cout<<setw(n-ccc.length()-1)<<setfill(cc)<<cc;字符串以长度n输出,不足n后面填充字符cc
setw()和setfill()只对紧跟在输出后的字符有效果;
3、printf("%05",r)就可以啦,%05d代表输出的数宽度为五位,不足五位前面补0
十二、map(L2)
map<---,---> mapname;
1、后面的---可以是结构体
比如:
struct node1
{
int data;
int next;
} ;
map<int,node1> mapname;
mapname[0].data = 1;
2、insert
mapname.insert(pair<int,sring>(1,"asdf"));
mapname.insert(map<int, string>::value_type (3, "student_three")); 不能覆盖已存在的key的对应的value
3、大小
size()
4、遍历
(1)、正向
map<int, string>::iterator iter = mapname.begin();iter!=mapname.end();iter++;
(2)、反向
map<double,int>::reverse_iterator iter;
for(iter = single.rbegin();iter!=single.rend();iter++){}
(3)、iter
iter->first:key的值
iter->second:value的值
5、查找
find()函数,返回当前位置的迭代器,否则返回结尾的迭代器
6、删除
erase(iter),删除iter位置的元素
erase(iter,iter+5)删除范围的元素(前闭后开集合)
erase(1)根据键值删除元素,删除键值为1 的元素
7、排序
自动按key升序排列
8、其他
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
9、map可嵌套
10、map<string,double> mapname 输出double时用printf("%lf",***)可以避免输出为int型(我用cout也输出的是double型···)
十三、set(L2)
根据元素键值自动排序,默认升序(从小到大)不允许键值重复
1. begin()--返回指向第一个元素的迭代器
2. clear()--清除所有元素
3. count()--返回某个值元素的个数
4. empty()--如果集合为空,返回true
5. end()--返回指向最后一个元素的迭代器
6. erase()--删除集合中的元素
erase(it) ------ 删除迭代器it对应的元素
erase(l, r) ------ 删除迭代器[l, r)之间的元素
7. find()--返回一个指向被查找到元素的迭代器
find(k) ------ 寻找k,若找到返回对应的迭代器,否则返回end();
8. insert()--在集合中插入元素
insert(a, b) ------ 插入指针[a, b)之间的元素,已有元素不会再次插入
11. lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
12. max_size()--返回集合能容纳的元素的最大限值
13. rbegin()--返回指向集合中最后一个元素的反向迭代器
14. rend()--返回指向集合中第一个元素的反向迭代器
15. size()--集合中元素的数目
16. upper_bound()--返回大于某个值元素的迭代器
17.结构体和set
/*
代码:按着成绩从大到小排序,成绩相同按着学号从小到大输出姓名
num name score
1 aa 1
2 bb 1
3 cc 2
运行结果
cc
aa
bb
这里也有疑惑,同样是重载运算符为什么score是大到小学号确是小到大?
*/#include<iostream>
#include<string>
#include<cstdio>
#include<map>
#include<set>
using namespace std;
struct stu
{
int num;
string name;
int score;
};
//进行比较要重载运算符,可以通过这种方式改变默认排序
bool operator < (const stu&a,const stu&b)
{
if(a.score!=b.score)
return a.score<b.score;
else if(a.score==b.score)
return a.num<b.num;
}
set<stu> s;
int main()
{
stu a,b,c;
a.name = "aa";
a.num = 1;
a.score = 1;
//插入结构体
s.insert(a);
b.name = "bb";
b.num = 2;
b.score = 1;
s.insert(b);
c.name = "cc";
a.num = 3;
a.score = 2;
s.insert(c);
set<stu>::iterator it;
for(it = s.begin();it!=s.end();it++)
{
a = (stu)(*it);//输出内容
cout<<a.name<<endl;
}
return 0;
}
十四、sort比较(L1)
1、
int a[10];
sort(a,a+10);默认是从小到大
2、
bool cmp(int a,int b)
{
return a>b;
}
sort(a,a+10,cmp);从大到小
十五、动态规划(凑零钱)
#include<iostream>
using namespace std;
int main()
{
int coins[3] = {2,3,5};
int money = 8;
int dp[10001] = {0};
int dp2[10001][3] = {0};
/*
下标i是要凑的钱数
dp[i]是凑够钱数所需的最小硬币数
dp2[i][j]是凑i时用的coins[j]的个数,用来求各个硬币用了多少
*/
for(int i=coins[0];i<=money;i++)
{
for(int j=0;j<3;j++)
{
if(coins[j]+coins[0]<=i||coins[j] == i)
{
dp[i] = min(dp[i-coins[0]]+1,dp[i-coins[j]]+1);
/*if(dp[i] == dp[i-coins[0]]+1)
dp2[i][0] = dp2[i-coins[0]][0]+1;
else
dp2[i][j] = dp2[i-coins[j]][j]+1;//这里是错的,本想输出最少钱数都用了哪些钱各多少*/
}
}
}
/*
i 从 coins[0]开始是因为最小的硬币面值是coins[0] ,比coins[0]小的面值凑不出来
j遍历coins数组,比较凑i-coins[j]与i-coins[0]哪个需要的硬币数最少,最后"+1"中的"1"是指coins[i]或者coins[0]这个硬币,最后得到凑i元最小硬币数
if中的条件是:
当i-coins[j]<coins[0]时, i-coins[j]这个面值是无法凑出的,因为 最小的硬币面值是coins[0] ,比coins[0]小的面值凑不出来,所以最后得到的结果一定是错的
所以在 i-coins[j]>=coins[0]时剩下的面值才能被凑出来换句话说只有这时 i-coins[j]才存在非0 最小值,比较才有意义
另一种情况就是i=coins[j]时,i = 2,j = 0时 2+2<=2这样就不能进循环但是2这个面值是可以凑出来的,所以要添加后面的条件考虑特殊情况
dp2[i][j] = dp2[i-coins[j]][j]+1;:凑i用的j的最小个数就是凑 i-coins[j]时用的j的最小个数加上1
*/
cout<<dp[money]<<endl;
cout<<"2: "<<dp2[money][0]<<endl;
cout<<"3: "<<dp2[money][1]<<endl;
cout<<"5: "<<dp2[money][2]<<endl;
return 0;
}
十五、排序算法:见数据结构
十六、并查集:查找源头是否相同