前言
寒假期间准备一下练一下OJ,对于我这个小菜鸟来说,打稳基础很是关键。听说过【算法竞赛入门经典】的大名,加上自己学习的是 C++ ,而这本书用的是 C ,多学一门语言也是不错的。因此决定每天最少看一章节。祝我成功,加油。
第一章
- 输入输出
C 语言的输入都是类似于占位符。
pirntf ("%.2f" ,b);//这里是保留b的二位小数,四舍五入。
scanf ,输入浮点数的时候 %lf 注意是 L 的小写 l,不是1。我试了好半天才发现不同。
scanf("%lf%lf",&a,&b); // 注意后面的一定要加上 & 符号。
在算法竞赛中,每行输出均应以回车符结束,包括最后一行。除非特别说 明,每行的行首不应有空格,但行末通常可以有多余空格。
程序的设计中肯定会用到数学知识,比如 : 两个偶数的和一定是 偶数。(鸡兔同笼)
总结
第一章是非常基础的知识,唯一令我感到惊讶的是 printf 函数保留小数的功能。其余的暂时没发现比 C++ 好到哪里。
第二章
循环
当前流行的竞赛平台中,int都是
32位整数,范围是-2147483648~2147483647。
long long 即可解决问题,其范围是-2 ^63 ~2 ^63 -1
- 10 ^-6 用 1e-6 表示
可以使用time.h和clock()函数获得程序运行时间。常数
CLOCKS_PER_SEC和操作系统相关,请不要直接使用clock()的返回值,而应总是除以
CLOCKS_PER_SEC。
25!末尾有6个0
- 碰到那种未指明有多少数据量的。利用 cin 的返回值 或者 scanf 的返回值
while(cin>>a);
while(scanf("%d",&a)==1) //C 语言中,scanf 的返回值是正确输入的数目。本例中还有一个 a 因此返回值为1
文件的输入输出
编程中读取文件内容,大量应用于测试数据较多的情况下
使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:
freopen(“input.txt”, “r”, stdin);
freopen(“output.txt”, “w”, stdout);
上述语句将使得scanf从文件input.txt读入,printf写入文件output.txt。
数组和字符串
数组的复制操作,因为没有经过什么系统的训练。因此字符串的复制我都是用 for 循环赋值。但是看了书后,学习到了 memcpy 。需要头文件 #include < string > (C++版)
memcpy(目的数组,起始数组,字节长)
举个栗子,从 int 型数组 a 复制 k 个数字到 int 型数组 b ,这样复制 memcpy(b,a,sizeof(int) *k)
全部复制使用 memcpy(b,a,sizeof(a));
数组清零
memcpy(a ,0,sizeof(a))
字符数组
字符串处理是常用的并且比较繁琐的一项基础能力。在 C 语言中,字符串就是字符数组(与 C++ 不同,C++ 有专门的string类)可以像处理普通数组那样处理字符串。
字符数组的读取
scanf("%s",s); //注意: s 为字符数组,前面没有 & 符号。 这样的读取遇到空格会停下来。
由于字符串的本质是数组,它也不是“一等公民”,只能用
strcpy(a, b),
strcmp(a, b),
strcat(a, b)
来执行“赋值”、“比较”和“连接”操作,而不能用“=”、“==”、 “<=”、“+”等运算符。
-
对于strcmp来说:
设这两个字符串为str1,str2,
若str1=str2,则返回零;
若str1<str2,则返回负数;
若str1>str2,则返回正数。
- strcat(char *,const char * ) //连接操作不言而喻
第四章
函数与递归
正式进入函数与递归的课程。
** C语言的结构体**
typedef struct {double x,y;} Point;
//其实按照 C++ 的写法也没问题
素数模板
int is_prime(int n)
{
if( n <= 1) return 0;
int m=floor(sqrt(n)+0.5); // floor() 函数为向下取整,这种写法实现了四舍五入
for( int i = 2 ; i<=m ; i++)
if( n % i == 0) return 0;
return 1;
}
- 尽量少使用指针,尽管他十分的巧妙。
- 以数组为参数调用函数时,实际上只有数组首地址传递给了函数,需要另
加一个参数表示元素个数。除了把数组首地址本身作为实参外,还可以利用指针加减法把其他元素的首地址传递给函数。无法使用 sizeof(数组名) 来获得数组的大小。
递归
递归:自己调用自己。
第五章 C++
又一次来到了 C++ 的世界,主要介绍 C++ 面向竞赛的一面。
- 使用 swap函数时,记得加上头文件 #include< algorithm>
在 C 语言中,strlen 是一笔不小的开销。相比于 C++ ,用 C 语言去处理字符串并不方便。
虽然string和sstream都很方便,但string很慢,sstream更慢,应谨慎使用
某个数字首次出现的位置=lower_bound(起始地址,结束地址,查找数)-起始地址(int类型)
stringstream 类
这个类在之前一直用来转化类型,如果使用一个对象对此转换,那么记住要clear() ,这里是它的另一种用途:stringstream 类具有压缩空格的功能。
#include <iostream>
#include <set>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string a, b;
cin >> a;
cout << a << endl;
for (int i = 0; i < a.length(); i++)
{
if(!isalpha(a[i]) )
a[i]=' ';
}
stringstream ss(a);
ss >> b;
cout << b << endl;
/*
如果 a输入为“........aaaaa”
那么 b 输出为 aaaaa
不包含空格!
*/
}
set 与 map
set 类,集合类的特点是内部没有相同的元素,并且具有按照从小到大排序的功能(内部已经排好了)。
方法 | 函数 |
---|---|
定义 | set < T> 名称 |
插入 | 名称.insert(dsa) |
- map 也具有从小到大排序的功能。
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<string, int> ss;
ss["dddcc"] = 4;
ss["accc"] = 14;
ss["c41"]=0;
for (auto it = ss.begin(); it!= ss.end(); it++)
{
cout << it->second << endl;
}
}
/*
14
0
4
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...
*/
优先队列
优先队列
是一种抽象数据类型(Abstract Data Type,ADT),行为有些像队列,但先出
队列的元素不是先进队列的元素,而是队列中优先级最高的元素,这样就可以允许类似
于“急诊病人插队”这样的事情发生。
pirority_queue 默认的是“数值越小的优先级别越低”,如果想“数值越小的优先级别越高”那么需要定义
priority_queue<int,vector< int>,greater< int> > 变量名
这里书上插入了一道《丑数题》,题目很有意思。另写了一篇博客。
应用:大整数类
暂时看不懂。。