算法竞赛入门知识干货

前言:本篇总结一部分来自刘汝佳老师的《算法竞赛入门经典》,一部分是个人竞赛学习中的一些算法知识点总结,是初学算法走了不弯路一点点积累起来的干货,对刚刚参加竞赛的盆友应该会很有帮助,如有不足请提出

一.程序设计入门

1.”%.1f” 保留小数点后一位

2.整数/整数=整数,浮点数/浮点数=浮点数

3.sqrt(x)=x的算数平方根

4.在算法竞赛中不要使用头文件conio.h,包括getch()、
clrscr()等函数。

5.在算法竞赛中,每行输出均应以回车符结束,包括最后一行。除非特别说明,每行的行首不应有空格,但行末通常可以有多余空格。另外,输出的每两个数或者字符串之间应以单个空格隔开。

6.三位数反转,反转后结果可以用printf函数控制
320→023:

 #include<stdio.h> 
int main() { 
	int n, m; 
	scanf("%d", &n); 
	m = (n%10)*100 + (n/10%10)*10 + (n/100); 
	printf("%03d\n", m); 
	return 0; 
}
 

320→23:

 #include<stdio.h> 
int main() { 
	int n, m; 
	scanf("%d", &n); 
	m = (n%10)*100 + (n/10%10)*10 + (n/100); 
	printf("%d\n", m); 
	return 0; 
}

7.输出\n:printf("\\\n"); 输出%d:printf("%%d")

8.int整数大小:-2147483648~2147483647,即-2^31~2^31-1

9.long long大小:-2^63~2^63-1 ,注意int输入的格式控制符改为%lld,Windows输入改为%I63d

二.循环结构程序设计

1.不拘一格地使用伪代码来思考和描述算法是一种值得推荐的做法。

2.x四舍五入:floor(x + 0.5); //floor返回不超过x的最大整数

3.浮点运算可能存在误差。在进行浮点数比较时,应考虑到浮点误差。

4.while适用于循环的次数是不确定的,而且n也不是“递增”式的循环。这样的情况

5.计算程序运行时间:printf("Time used = %.2f\n", (double)clock() / CLOCKS_PER_SEC);//在程序结束之前调用此函数,便可获得整个程序的运行时间。这个时间除以 常数CLOCKS_PER_SEC之后得到的值以“秒”为单位。用文件方式读入,要不然会计算键盘输入的时间
可以使用time.h和clock()函数获得程序运行时间。常数
CLOCKS_PER_SEC和操作系统相关,请不要直接使用clock()的返回值,而应总是除以CLOCKS_PER_SEC

6.文件读写操作
文件读入:freopen(“文件地址”,“r”,stdin);
写到文件:freopen(“文件地址”,“w”,stdou);

7.在观察无法找出错误时,可以用“输出中间结果”的方法查错

8.当输入数据个数不定时,且没有限制条件:

while(scanf("%d", &x) == 1) 
{
      执行操作	
}

直接用键盘停止输入
在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再按Enter 键,即可结束输入。在Linux下,输入完毕后按Ctrl+D键即可结束输入。

9.变量在未赋值之前的值是不确定的。特别地,它不一定等于0

10.当变量大于其类型最大值是会产生溢出,运行结果会出现#INFO
解决技巧:如1/i*i 溢出 变化成:1/i/i

11.巧妙用输出来控制精确:a精确到c位:printf(“%.*f”,c,a);

三.数组和字符串

1.在算法竞赛中,常常难以精确计算出需要的数组大小,数组一般会声明得稍 大一些。在空间够用的前提下,浪费一点不会有太大影响。

2.比较大的数组应尽量声明在main函数外,否则程序可能无法运行。

3.数组a赋值k个元素到数组b

   #include<string.h>
   memcpy(b,a,sizeof(类型)* k)

给数组每个元素赋相同初值

  memset(数组名,初值,sizeof(数组名))//常用于初始化
  或者
  memset(数组名,初值,sizeof(类型)*大小)
注意:int类型只能赋值0-1

4.字符串数组char s[m][n] 可以用scanf(“%s”,s[i])读取第i个字符串

5.C语言中的字符串是以“\0”结尾的字符数组,可以用strlen(s)返回字符串s中结束标记之前的字符个数。

6.两个数组操作函数

赋值:strcpy(a,b)//b赋值给a
比较:strcmp(a,b)//a>b返回1
连接:strcat(a,b)//返回里连接后字符串

7.头文件include<ctype.h>

  isalnum(a)   测试传入参数是否为为字母或数字,真返回值为非零
  isalpha(a)   测试传入参数是否为字母,真值返回非零
  isdigit(a)   测试传入参数是否为数字,真值返回非零

8.如果char 值为正,则是西文字符;如果为负,则是汉字的前一半(这时需要再读一个char)

9 函数的参数和返回值最好是“一等公民”,如int、char或者double等。其他“非 一等公民”作为参数和返回值要复杂一些。如果函数不需要返回值,则返回类型应写成 void。

10.在C语言中,定义结构体的方法为“struct 结构体名称{ 域定义 };”,注意花括号的后面还有一个分号。

11.为了使用方便,往往用“typedef struct { 域定义; }类型名;”的方式定义一个新类型名。这样,就可以像原生数据类型一样使用这个自定义类型。

12.结构体定义

第一种 struct point{int x ;int y};           使用: struct point  a;
第二种 typedef struct{int x;int y}point;     使用:point a;  

13.对复杂的表达式进行化简有时不仅能减少计算量,还能减少甚至避免中间结果溢出

14.“判断一个事物是否具有某一性质”的函数还有一个学术名称——谓词(predicate)
建议把谓词(用来判断某事物是否具有某种特性的函数)命名成is_xxx的形式,返回int值,非0表示真,0表示假。

15.在调用函数调用数组时,参数传递是传递数组的首地址,所以不能用sizeof(a)计算数组的大小,正确做法是在传递数组长度参数n

16.While()输入巧用

While(scanf("%d%d%d",&a,&b,&c)==3){}
//scanf(“%d%d%d”)==3  是判断是否输入完毕和输入的数是否有效

while(scanf("%d%d%d",&a,&b,&c)!=EOF){}
//EOF表示结束标志

while(getchar()!='\n'){};
//利用回车来巧妙结束循环

17.全局变量要少用

18.strcmp(a,b)函数

比较字符串a,b大小;相等返回0;a>b返回1;a<b返回-1

19.注意:在参加比赛时,千万不要在使用for循环的时候命名变量,可能会因为编译器兼容的原因是编译不通过,直接零分,最好在函数开始就命名

20.在实际问题中,如果利用输出函数来规定输出的小数位数,很可能会因为四舍五入而得不到正确结果,这是可以用这种方法来解决四舍五入

a=(int)(a*100)/100.0;  //防止四舍五入,首先将多余位给切掉,再还原成小数
printf("%.2f\n",a);

//注意a*100一定要加括号

四.C++

1.头文件

#include<stdio.h>    →    #include< cstdio >
#include<string.h>   →    #include< cstring >
#include<math.h>     →    include < cmath >	
#include<ctype.h>    →    include< ctype >
#include< iostream >              提供了输入输出流
#include< algorithm >             提供常用算法

2.using namespace std 名称空间(写在函数开头)

3.声明数组: #define maxn 50 → const int maxn=50

4.C++中的数据类型和C语言很接近,最显著的区别是多了一个bool来表示布 尔值,然后用true和false分别表示真和假。虽然仍然可以用int来表示真假,但是用bool可以 让程序更清晰

5.void swap2(int& a, int& b) 如果在参数名之前加一个“&”符号,就表示这个参数按照传引用(byreference)的方式传递,而不是C语言里的传值(by value)方式传递。这样,在函数内改变参数的值,也会修改到函数的实参。

6.C++中的引用就是变量的"别名",它可以在一定程度上代替C中的指针。例如,可以用“传引用”的方式让函数内直接修改实参。

四.小知识

1.数学函数 double ceil(double);
功能:返回大于或者等于指定表达式的最小整数

2.scanf()函数输入字符串时,当读到空格就会停止输入
例如

char a[20] sacnf(%s”,a),输入”I LOVE YOU”最后读入的只有‘I’

scanf(%[^\n],a)除了换行符外其他字符全部接收

3.负数的二进制(表示负数的补码)

"-1"转为二进制的过程
第一步:找原码"1"8位二进制表示为00000001
第二步:找原码的反码为11111110
第三步:找补码(反码加一):11111111

4.各输出格式控制代码如下:

    int PrintVal = 9;
 
    /*按整型输出,默认右对齐*/
    printf("%d\n",PrintVal);
    
    /*按整型输出,补齐4位的宽度,补齐位为空格,默认右对齐*/
    printf("%4d\n",PrintVal);
    
    /*按整形输出,补齐4位的宽度,补齐位为0,默认右对齐*/
    printf("%04d\n",PrintVal);

    /*按16进制输出,默认右对齐*/   
    printf("%x\n",PrintVal);
    
    /*按16进制输出,补齐4位的宽度,补齐位为空格,默认右对齐*/
    printf("%4x\n",PrintVal);
    
    /*按照16进制输出,补齐4位的宽度,补齐位为0,默认右对齐*/
    printf("%04x\n",PrintVal);

    /*按8进制输出,默认右对齐*/
    printf("%o\n",PrintVal);
    
    /*按8进制输出,补齐4位的宽度,补齐位为空格,默认右对齐*/
    printf("%4o\n",PrintVal);
    
    /*按照8进制输出,补齐4位的宽度,补齐位为0,默认右对齐*/
printf("%04o\n",PrintVal);

5.等差数列通项,前n项和

   通项:an=a1+(n-1)*d;
   
   前n项和:Sn=a1*n+(n(n-1)d)/2;
            Sn=n(a1+an)/2;

6.等比数列通项,前n项和

通项:  an=a1*q^(n-1);

前n项和: 当q=1时       Tn=n*a1;
         当q!=1时       Tn=a1(1-q^n)/(1-q)      
      

7.只有以\0结束的字符数组才可以以s%的方式用printf输出,否则输出会 非常奇怪,自己在char数组上构造一个字符串的时候,忘记在末尾加\0可能会导致访问非法内存的错误

8.字符串拼接函数: char* strcat(char *dest,char *source),可以将source字符串拼接到dest后面

9.声明数组全局变量会自动清零,局部变量需要手动清零

10.char a[10]; strlen(a+1)会从第二个数开始数到数组结尾,不要将strlen(a)写在for循环里面,否则循环一次计算一次会大大减低速度,正确做法是保存到变量中;

11.闰年:
满足一下任意一个条件都是闰年
1.年份非整百且能被4整除的为闰年
2.年份能被四百整除的是闰年(闰年二月29天,平年28天,大月31天,小月30天)

判断是否为闰年代码:

 int is_leap_year(int year)
        {
            if(year%400==0||(year%100!=0&&year%4==0))
              return 1;
            else
               return 0;
          }

12.蔡基姆拉尔森公式
在这里插入图片描述
13.C语言qsort()排序函数(默认从小到大,从大到小直接对cmp返回值取反)

#include<stdlib>
   int cmp(const void*a,const void*b)
{
return (*(int*)a-*(int*)b);
}
qsort(起始地址,排序元素个数,sizeof(类型),cmp); 

14.c++排序函数

#include<algorithm>
using namespace std;
sort(a,a+n);

如果要从大到小排序则加一个函数
sort(a,a+n;cmp);
bool cmp(int a,int b)
{return a>b;}

21.万能头文件:#include<bits/stdc++.h>

22.round(a)求离a的最近整数

23.常用数学函数(math.h)

1fabs(double x)  求绝对值
(2floor(double x)向下取整  ceil(double x)向上取整
(3pow(double x,double y)x 的y次方
(4sqrt(double)返回算术平方根

24.String二维数组string mp[1005]初始化

for(int i=0;i<n;i++)mp[i].resize(m);//先要个数撑起来

for(int i=0;i<n;i++)mp[i].resize(m,t)//会初始化为t值

25.周期性运动通式

 guess(起点,方向,步数){
      while(步数--){
 	       终点=(起点+方向+周期-1)%周期+1}

26.一颗包含有2019个节点的二叉树,最多包含多少个叶节点

各个节点之间的关系:n=n0+n1+n2,为了使叶子结点(n0)最多,必须n1最小即设为0; 有关系n0=n2+1
得到n2=(2019-1)/2=1009,所以n0=1010;

27.用while输入字符串

while(c=getchar())!=EOF&&c!=’\n’){
          a[len++]=c;
}
注意:c=getchar()必须打包处理
  • 21
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值