算法笔记学习
1 C/C++基础
1 int的无穷大写法(INF)
const int INF=0x3fffffff;
2 scanf函数
常见数据类型变量的scanf格式符
数据类型 | 格式符 |
---|---|
int | %d |
long long | %lld |
float | %f |
double | %lf |
char | %c |
字符串(char数组) | %s |
3 三种实用的输出格式
(1)%md
%md可以使不足m位的int型变量以m位进行右对齐输出,其中高位用空格补齐;如果变量本身超过m位,则保持原样。
例如:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=123,b=1234567;
printf("%5d\n",a);
printf("%5d\n",b);
return 0;
}
输出:
可以看见,123有三位数字不足5位,因此前面自动用两个空格填充,使整个输出凑齐5位。
(2)%0md
当变量不足m位时,将在前面补足足够数量的0,而不是空格
例如:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=123,b=1234567;
printf("%05d\n",a);
printf("%05d\n",b);
return 0;
}
输出:
(3)%.mf
可以让浮点数保留m位小数输出,规则为四舍六入五成双。在题目要求保留xx位小数或精确到小数点后xx位时使用。
例如:
#include<bits/stdc++.h>
using namespace std;
int main(){
double d1=12.3456;
printf("%.0f\n",d1);
printf("%.1f\n",d1);
printf("%.2f\n",d1);
printf("%.3f\n",d1);
printf("%.4f\n",d1);
return 0;
}
输出:
4 typedef
常用于定义long long
typedef long long LL;
5 常用math函数
(1) fabs(double x)
该函数用于对double型变量取绝对值
(2) floor(double x),ceil(double x)
分别用于double类型变量的向下取整和向上取整,返回类型为double型
(3) pow(double r,double p)
用于返回 r p r^p rp,要求二者都为double型
(4) sqrt(double x)
用于返回double型变量的算术平方根
(5) log(double x)
用于返回double型变量的以自然对数为底的对数
注意:C语言中没有求任意底数的函数,必须运用换底公式
l o g a b = l o g e b / l o g e a log_ab=log_eb/log_ea logab=logeb/logea
(6) round(double x)
用于将double类型变量x四舍五入,返回类型也是double型,需要进行取整
注:在看代码的过程中,if(n)表示if(n!=0);if(!n)表示if(n==0)
6 break与continue语句
break:在需要的场合下直接退出循环
continue:当满足条件时执行continue,可以将下面的部分切断不执行,然后继续进入下一层循环
7 数组注意
在定义了长度为size的一维数组后,只能访问下标为0—size-1的元素,即int a[10]可以访问a[0],a[1],a[2]…a[9]。而不能访问a[10]。
8 memset函数——对数组中每一个元素赋相同的值
格式:
memset(数组名,0,sizeoof(数组名));
对数组名的所有元素置零
适用于一维和二维数组
9 strlen()函数
可以得到字符数组中第一个\0之前的字符的个数
格式:
strlen(字符数组);
2 算法入门——模拟
所谓模拟,就是题目怎么说,人就怎么写,不太涉及算法,根据题目描述来进行代码的编写,考察代码能力。
2.1 简单模拟
1 害死人不偿命的(3n+1)猜想
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,step=0;
scanf("%d",&n);
while(n!=1){
if(n%2==0)
n=n/2;
else
n=(3*n+1)/2;
step++;
}
printf("%d\n",step);
return 0;
}
2 挖掘机技术哪家强
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int school[maxn]={0};//记录每个学校的总分
int main(){
int n,schID,score;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&schID,&score);
school[schID]+=score;
}
int k=1,max=-1;//最高分学校的ID及其总分
for(int i=1;i<=n;i++){
if(school[i]>max){
max=school[i];
k=i;
}
}
printf("%d %d\n",k,max);
return 0;
}
2.2 查找元素
1 找x
#include<bits/stdc++.h>
using namespace std;
const int maxn=210;
int a[maxn];
int main(){
int n,x;
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&x);//输入需要查询的数字
int k;
for(k=0;k<n;k++){
if(a[k]==x){
printf("%d\n",k);
break;
}
}
if(k==n){
printf("-1");
}
}
return 0;
}
2.3 图形输出
1 跟奥巴马一起编程
#include<bits/stdc++.h>
using namespace std;
int main(){
int row,col;
char c;
scanf("%d %c",&col,&c);
if(col%2==1)
row=col/2+1;
else
row=col/2;
for(int i=0;i<col;i++){
printf("%c",c);
}
printf("\n");
for(int i=2;i<row;i++){
printf("%c",c);
for(int j=0;j<col-2;j++){
printf(" ");
}
printf("%c\n",c);
}
for(int i=0;i<col;i++){
printf("%c",c);
}
return 0;
}
2.4 日期处理
1 日期差值
#include<bits/stdc++.h>
using namespace std;
int month[13][2]={
{0,0},{31,31},{28,29},{31,31},{30,30},
{31,31},{30,30},{31,31},{31,31},{30,30},
{31,31},{30,30},{31,31}
};
bool isLeap(int year){//判断是否是闰年
return (year%4==0&&year%100!=0)||(year%400==0);
}
int main(){
int time1,y1,m1,d1;
int time2,y2,m2,d2;
while(scanf("%d%d",&time1,&time2)!=EOF){
if(time1>time2){
int temp=time1;
time1=time2;
time2=temp;
}
y1=time1/10000,m1=time1%10000/100,d1=time1%100;
y2=time2/10000,m2=time2%10000/100,d2=time2%100;
int ans=1;
while(y1<y2||m1<m2||d1<d2){
d1++;
if(d1==month[m1][isLeap(y1)]+1){
m1++;
d1=1;
}
if(m1==13){
y1++;
m1=1;
}
ans++;
}
printf("%d\n",ans);
}
return 0;
}
2.5 进制转换
模板代码:
对一个P进制的数,要转换为Q进制,需要分为两步
(1)将P进制数x转换为十进制数y
int y=0,product=1;
while(x!=0){
y=y+(x%10)*product;
x=x/10;
product=product*P
}
(2)将十进制数y转换为Q进制数z
int z[40],num=0;
do{
z[num++]=y%Q;
y=y/Q;
}while(y!=0);
1 D进制的A+B
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b,d;
scanf("%d%d%d",&a,&b,&d);
int sum=a+b;
int ans[31],num=0;
do{
ans[num++]=sum%d;
sum/=d;
}while(sum!=0);
for(int i=num-1;i>=0;i--){
printf("%d",ans[i]);
}
return 0;
}
2.5 字符串处理
1 回文串
#include<bits/stdc++.h>
using namespace std;
const int maxn=256;
bool judge(char str[]){
int len=strlen(str);
for(int i=0;i<len/2;i++){
if(str[i]!=str[len-1-i]){
return false;
}
}
return true;
}
int main(){
char str[maxn];
while(gets(str)){
bool flag=judge(str);
if(flag==true){
printf("YES");
}else{
printf("NO");
}
}
return 0;
}
3 算法初步
3.1 排序
对于排序题,一般只用sort函数(c++)
排序题型的常用解题步骤:
1 相关结构体的定义
对排序题,一定会在题目中给出个体的许多信息,例如学生有姓名,准考证号,分数,排名等信息。可以用一个结构体数组来表示多个个体。例如:
struct Student{
char name[10];//姓名
char id[10];//准考证号
int score;
int r;//排名
}stu[100010];
2 cmp函数的编写
在使用sort进行排序时,需要提供cmp函数实现排序规则。如以下要求:对所有学生按分数从高到低进行排序,分数相同的按姓名的字典序从小到大排序。
实际排序规则等价描述为:
(1)如果两个学生分数不相同,那么分数高的排在前面
(2)否则,将姓名字典序小的排在前面
对应的cmp函数如下:
bool cmp(Student a,Student b){
if(a.score!=b.score)
return a.score>b.score;
else
return strcmp(a.name,b.name)<0;
}
注:strcmp(str1,str2)当str1的字典序小于str2时返回一个负数,等于时返回0,大于时返回一个正数
3 排名实现
很多排序题都会在排序后计算每一个个体的排名,且规则一般是:分数不同排名不同,分数相同的排名相同且占用一个排名。如五个学生成绩为90,88,88,88,86.那么排名为:1,2,2,2,5
思路:
先将数组的第一个个体的排名记为1,然后遍历剩余个体。如果当前个体的分数等于上一个个体的分数,那么当前个体的排名等于上一个个体的排名;否则,当前个体的排名等于数组下标加1
stu[0].r=1;
for(int i=1;i<n;i++){
if(stu[i].score==stu[i-1].score){
stu[i].r=stu[i-1].r;
}else{
stu[i].r=i+1;
}
}