CSP算法题基础(1)
CSP算法题基础
-
C++程序里面会添加许多头文件,头文件的格式一般是
1763#include<头文件名>
我们先接触这两个头文件cstdio和iostream,其中cstdio包含了两个函数printf输出函数和scanf输入函数;第二个头文件是iostream,主要包含了cin,cout,endl三个函数。
using namespace std; // 命令空间指的是 保证在同一命名空间里面,变量名不冲突即可。不同的命名空间里面的变量名是可以相同,因为命名空间不同。命名空间一般我们都是使用在较大项目中,这种项目的变量一般比较多,有使用价值,算法比赛中,意义不大。
bool false/true 1Byte
char 1Byte
int范围是\([-2^{31},2^{31}-1]\) 一共是\(2^{32}\)个数。十进制下这些数是-2147483648 to 2147483648。 4Byte
float 1.23,1(整数也可以被浮点数表示)。此外,还支持科学计数法,比如1.23e2就是\(1.23*10^2\) ,float的精度比较低,通常只有6-7位有效数字 4Byte
double 双精度浮点数,它的精度比较高,通常是15-16位有效数字 8Byte
long long (int的扩展版) 它的表示范围是\([-2^{63},2^{63}-1]\) 8Byte
long double(double的扩展版),它的精度是18-19位 16Byte
常用编辑器显示float和double类型一般是6位,不足6位补0,超过6位,四舍五入截断。
使用经验:最好使用int,然后使用double,最后使用float
注意数值整数也有类型:
long long m =13123123234LL; //对,必须对整数添加后缀进行说明该整数是longlong类型整数 long long m = 13123123234; //错,整数数值类型和变量类型不匹配,要是不添加的话,这个m可能就变成负数了 long double m = 231312.1312312lf // 对,数值末尾要添加标记,说明数值整数类型
-
输入输出算法
简单输入输出格式:
#include<iostream> using namespace std; int main(){ int a ,b; cin >> a >>b; cout << a+b<<endl; return 0; }
segmentation fault(数组越界)
一次有多个输出
#include<iostream> using namespace std; int main(){ int a,b; cin>>a>>b; cout<<a+b<<' '<<a*b<<endl; return 0; }//输出比较自由,有多种输出格式,但是输出格式是一样 #include<iostream> using namespace std; int main(){ int a,b; cin >> a;//输入 cin >> b; cout<<a+b;//输出 cout<<' '; cout<<a*b; cout<<endl; return 0; }
-
利用scanf和printf进行输入输出
#include<cstdio> #include<iostream> using namespace std; int main(){ int a,b; scanf("%d %d",&a,&b); //float对应的输入格式%f printf("%d %d\n",a+b,a*b);//float对应的输出格式%f return 0; } ———————————————————————————————————————————————— #include<cstdio> #include<iostream> using namespace std; int main(){ float a,b; scanf("%f %f",&a,&b); printf("%f %f\n",a+b,a*b); return 0; }
利用printf和scanf需要判断输入输出类型,但是利用cin、cout不用判断输出输入类型。
发现当输入输出都是float的时候,确实精确度(有效位数)是7位
当我们想保留两位小数的时候,需要对输出进行修改
printf("%.2f %.2f\n",a+b,a*b);
char类型
int main(){
char a,c;
scanf("%c %c",&a,&c); //char类型对应的printf输出格式是 %c,注意%c是可能读入空格,键盘输入q w,输出q w
//键盘键入q ,输出就是q |。
printf("%c %c",a,c);
}
%c读入空格,输出就是空格
cin>>输入 和 标准输入输出scanf 相比,cin能够过滤掉空格,scanf不能过滤空格,cin效率比较低,但是scanf效率却高
double类型
int main(){
double a,b;
scanf("%lf%lf",&a,&b);
printf("%lf %lf",a,b);//对于double类型,标准输入输出格式是 %lf
}
对scanf的标准输入结束标记应该是return键,像上图输入第一个数据后,按下return键或者按下空格(对照scanf输入字符串,此时的空格起的作用是分隔两部分输入),再接着输入第二个数
long long类型:
int main(){
long long a,b;
scanf("%lld%lld",&a,&b);
printf("%lld%lld",a,b);
return 0;
/*
float %f
int %d
double %lf
char %c
long long %lld
*/
}//输入输出是%lld
-
加减乘除以及取模运算
#include<iostream> using namespace std; int main(){ cout<< 5 % 2 <<endl; // 取模得到1 cout<< -5 % 2 <<endl; // 取模得到-1 return 0; // 取模结果完全取决于第一个数的正负,后面的数无所谓 }
-
不同的变量类型之间可以相互转化
从低精度到高精度没有任何问题,从高精度到低精度会损失一些信息,仅此而已。
#include<iostream> using namespace std; int main(){ int a = 5; float b = a; printf("%f",b); return 0; } //得到的结果就是5.000000 float类型 _____________________ #include<iostream> using namespace std; int main(){ float a = 3.14; int b = a; printf("%d",b); return 0; } //得到的结果是3
int(看成低精度) 转float,会白白提高精度;
float转成int,会向下取整
int和char类型之间的转化
#include<iostream> using namespace std; int main(){ int var = 97; char temp = var; printf("%c",temp); return 0; } ____________ int main(){ char var = 'a'; int tmp = (int)var; printf("%d",tmp); } cout << 'A'+2 << endl;//的结果会是67,char+int会变成int类型 cout << 3.14+2 << endl; // 的结果会是5.14,float+int会变成float。其实最终变成的类型都是倾向于变得比较强
例题:
- 输入三个数,输出第二个整数:
#include<iostream> using namespace std; int main(){ int a,b,c; cin>> a >> b >> c; cout<< b <<endl; return 0; }
- 输入a,b,c,计算\((a+b)*c\)的值:
#include<iostream> using namespace std; int main(){ int a,b,c; scanf("%d%d%d",&a,&b,&c); printf("%d",(a+b)*c); return 0; }
其他具体题目见acwing
注意还有一个头文件
#include<bits/stdc++.h>
- 给一个雇员名字、底薪、销售额,计算雇员工资
#include<iostream> #include<cstdio> #include<string>//可以不用写这个库,<string>被包含再<iostream>库里 using namespace std; int main(){ string name; float sal,sales; //读入字符串,需要使用string 数据类型, //string 数据类型只能用cin,使用scanf读入会有额外的写法 cin >> name; cin >> sal >> sales; printf("TOTAL = R$ %.2f",sal+0.15*sales); return 0; }
abs函数被封装在
库 - 钞票和硬币转换
//用浮点数存在精度问题,建议转换成整数后用整数来做 #include<iostream> #include<cstdio> using namespace std; int main(){ //由N的范围,从输入样例发现都是保留两位小数,所以建议乘上100,发现之后还是没有爆掉 float N; cin >> N; int New_N = N*100; s100 = New_N/10000; New_N = New_N - s100*10000; s50 = New_N/5000; New_N = New_N - s50*5000; s20 = New_N/2000; New_N = New_N - s20*2000; s10 = New_N/1000; New_N = New_N - s10*1000; s5 = New_N/500; New_N = New_N - s5*500; s2 = New_N/200; New_N = New_N - s2*200; s1 = New_N/100; New_N = New_N - s1*100; s_50 = New_N/50; New_N = New_NN - s_50*50; s_25 = New_N/25;New_N = New_N - s_25*25; s_10 = New_N/10;New_N = New_N - s_10*10; s_05 = New_N/5;New_N = New_N - s_05*5; s_01 = New_N/1; cout<<"NOTAS:"<<endl; printf("%d nota(s) de R$ 100.00\n",s100); printf("%d nota(s) de R$ 50.00\n",s50); printf("%d nota(s) de R$ 20.00\n",s20); printf("%d nota(s) de R$ 10.00\n",s10); printf("%d nota(s) de R$ 5.00\n",s5); printf("%d nota(s) de R$ 2.00\n",s2); cout<<"MOEDAS:"<<endl; printf("%d moeda(s) de R$ 1.00\n",s1); printf("%d moeda(s) de R$ 0.50\n",s_50); printf("%d moeda(s) de R$ 0.25\n",s_25); printf("%d moeda(s) de R$ 0.10\n",s_10); printf("%d moeda(s) de R$ 0.05\n",s_05); printf("%d moeda(s) de R$ 0.01\n",s_01); return 0; }
-
printf语句(在
里面) #include<iostream> using namespace std; int main(){ double a =3.1415926; printf("%.lf",a); //保留三位小数 return 0; }
格式化输出
#include<iostream> using namespace std; int main(){ int a=1,b=23,c=456; double f = 12.321 //固定宽度输出 printf("%5d",a); //%d添加5表示,保留5个字符的位置,空位让空格填充,先输出1,然后从右向左填充空格 printf("%5d",b); //或者可以这样说,//先输出空格//再输出1//,一共输出5个字符位置 printf("%5d",c); //浮点数也有类似的输出格式 printf("%5.1lf",f); //这里应该表示的是:浮点数固定宽度宽是5位(默认用空格填充),保留1位小数,这里的5位是包含小数点的一位,所以输出应该是: 12.3,刚好5位 printf("%05.1lf",f); //这里表示固定宽度是5,输出应该是:012.3,第一位不用空格填充,而是用特定字符0 printf("%-5.1lf!",f);//表示5位字宽,保留一位小数。但是先数字,后补空格(经过试验,发现右边不能补0,只能补空格) return 0; }
printf("%-5d",a); printf("%-5d",b); //同样的可以这样理解-5d,是先输出数字,再输出空格,一共输出5个字符的位置,前面补空格 printf("%-5d",c); //输出格式如下
//除了补充空格,还可以补充字符,比如补充0
printf("%05d",a);
printf("%05d",b);
printf("%05d",c); //输出格式如下所示
printf("%5.1lf",f); //这里应该表示的是:浮点数固定宽度宽是5位(默认用空格填充),保留1位小数,这里的5位是包含小数点的一位,所以输出应该是: 12.3,刚好5位
%8.3lf 表示一共8位有效数字数,保留3位小数,在前面补空格;
%08.3lf 表示一共8位有效数字,保留3位小数,在前面补充0;
%-8.3lf 表示一共8位有效数字,保留3位小数,在后面补充空格
实现输入两个数,输出其中较大一个,不要使用库函数
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int a,b;
cin>>a >> b;
if(a > b) printf("%d",a);
else printf("%d",b);
return 0;
}
输入三个数,利用判断结构,输出其中较大的一个数
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int a,b,c;
cin >> a >> b >> c;
if(a > b){
if(a > c){
cout<<a<<"最大"<<endl;
}else{
cout<<c<<"最大"<<endl;
}
}
else{//这里省略的是a<b
if(b > c){
cout<<b<<"最大"<<endl;
}else{
cout<<c<<"最大"<<endl;
}
}
return 0;
}
输入一个0-100的分数,如果大于等于85,输出A;如果大于等于70,并且小于85,输出B;如果大于等于60,并且小于70,输出C;如果小于60,输出D
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int score;
cin >> score;
if(score >= 85){
cout<<"A"<<endl;
}else{
if(score >= 70){
cout<<"B"<<endl;
}else{
if(score >= 60){
cout<<"C"<<endl;
}else{
cout<<"D"<<endl;
}
}
}
return 0;
}
简易计算器,输入两个数以及一个算子符号,输出正确结果
注意:需要判断除数为0,以及不是+-*\的符号
#include<csdtio>
#include<iostream>
using namespace std;
int main(){
//cin可以帮助我们省略空格、回车,scanf不能忽略空格和回车
int x1,x2;
char opa;
cin >> x1 >> x2 >> opa;
if(opa == '+'){
cout<<x1 + x2 <<endl;
}else{
if(opa == '-'){
cout << x1 - x2 <<endl;
}else{
if(opa == '*'){
cout << x1*x2<<endl;
}else{
if(opa == '/'){
if(x2 == 0){
cout << "Divided by zero!"<<endl;
}
}else{
cout << "Invalid operator!"<<endl;
}
}
}
}
return 0;
}
判断闰年
#include<iostream>
using namespace std;
int main(){
int year;
cin >> year;
if(year % 100 ==0){
if(year % 400 == 0){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
}else{
if(year % 4 == 0){
cout<<"yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
return 0;
}
三元素交换的swap函数手写
// a b c按照升序排列
int temp;
if(a > b){
temp = b;
b = a;
a = temp; //两两交换
}
if(a > c){
temp = a;
a = c;
c = temp;
}
if(b > c){
temp = b;
b = c;
c = temp;
}