洛谷入门题库详细思路及优化(C++)①

题目均来自洛谷的入门题单,代码有参考洛谷题解,注意分辨。 

一、顺序结构

⑴B2025(输出)

注意:该题只需要输出,无需输入,可自行忽略 

 ①使用cin和cout

#include<iostream> 
using namespace std;

int main()
{
	char a; 
	cin>>a;
	
	cout<<"  "<<a<<endl<<" "<<a<<a<<a<<endl<<a<<a<<a<<a<<a<<endl<<" "<<a<<a<<a<<endl<<"  "<<a<<endl;  
	return 0;
} 

注意:cin输入时不可使用endl,当输入格式要求换行和空格时,都可忽视,只有当你输入了足够的变量并按下回车时,程序才会运行,它会自动跳过你输入的空格; 

注意:并不需要在变量a后输入空格,直接换行效果是一样的

②使用scanf和printf 

#include<iostream> 
using namespace std;

int main()
{
	char a; 
	scanf("%c",&a);
	
	printf("  %c\n %c%c%c\n%c%c%c%c%c\n %c%c%c\n  %c\n",a,a,a,a,a,a,a,a,a,a,a,a,a); 
	return 0;
}

 ⑵P1000(多行字符串的输出)

问题:多行字符串的输入?

①printf函数输出多行字符串(每行字符串都用”“括起来,并在末尾字符使用\n换行符换行)

#include<iostream> 
using namespace std;

int main()
{
	printf(
	"                ********\n"
	"               ************\n"
	"               ####....#.\n"
	"             #..###.....##....\n"
	"             ###.......######              ###            ###\n"
	"                ...........               #...#          #...#\n"
	"               ##*#######                 #.#.#          #.#.#\n"
	"            ####*******######             #.#.#          #.#.#\n"
	"           ...#***.****.*###....          #...#          #...#\n"
	"           ....**********##.....           ###            ###\n"
	"           ....****    *****....\n"
	"             ####        ####\n"
	"           ######        ######\n"
	"##############################################################\n"
	"#...#......#.##...#......#.##...#......#.##------------------#\n"
	"###########################################------------------#\n"
	"#..#....#....##..#....#....##..#....#....#####################\n"
	"##########################################    #----------#\n"
	"#.....#......##.....#......##.....#......#    #----------#\n"
	"##########################################    #----------#\n"
	"#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#\n"
	"##########################################    ############\n"
		);
	
	return 0;
}

注意:输入时间上 ,②优于①

 ②C++11标准下,使用cout<<R"()";可输出多行字符串(不可以输出变量)

#include<iostream> 
using namespace std;

int main()
{
	cout<<R"(                ********
               ************
               ####....#.
             #..###.....##....
             ###.......######              ###            ###
                ...........               #...#          #...#
               ##*#######                 #.#.#          #.#.#
            ####*******######             #.#.#          #.#.#
           ...#***.****.*###....          #...#          #...#
           ....**********##.....           ###            ###
           ....****    *****....
             ####        ####
           ######        ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
##########################################    #----------#
#.....#......##.....#......##.....#......#    #----------#
##########################################    #----------#
#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#
##########################################    ############)";
	return 0;
}

⑶ P1001

①自己写的

#include<iostream>
using namespace std;

int main()
{
	int a,b,sum;
	cin>>a>>b;
	
	sum=a+b;
	cout<<sum;
	return 0;
}

注意:要慢慢开始积累一些常用的英文,以后代码变量名需要用英语来写,不然代码量一大,一堆abcdefg会使代码可读性降低,自己也会看不懂自己写的啥,注释一堆也麻烦。

sum表示“总和”的意思。

②比①更优。

②别人写的(cout可以直接输出表达式的结果)

#include<iostream>
using namespace std;

int main()
{
	int a,b;
	cin>>a>>b;
	cout<<a+b;
	return 0;
}

⑷P5704(字符与其ASCII值)

问题:C++中字符与ASCII码的关系 

#include<iostream>
using namespace std;

int main()
{
	char a;//此处只输入小写字母 
	cin>>a;
	cout<<char(a-32);//a会自动转化为小写字母的ASCII值;小写字母ASCII值-32=大写字母ASCII值;用char()进行强制类型转化,将int类型的大写字母ASCII值转化为相对应的char类型字符 
	return 0;
}

 注意:C++中每个字符都有其对应的ASCII码值,例如A的ASCII值为65,a的ASCII值比A的ASCII值大32。由此我们可知所有大小写字母的ASCII值。A为65,B为66....,a为65+32;

当然,也可以不记上面所说的东西。我们只要让对应的小写字母的ASCII-大写字母的ASCII值就能得到差值32.

#include<iostream>
using namespace std;

int main()
{
	char a;
	cin>>a;
	cout<<char(a-('a'-'A'));
	return 0;
}

(5)P5705(字符串逆序输出)

#include<iostream>
using namespace std;

int main()
{
	char a,b,c,d;
	scanf("%c%c%c.%c",&a,&b,&c,&d);
	printf("%c.%c%c%c",d,c,b,a);
	return 0;
}

注意:这两种写法大差不差。有个点需要注意,就是读入字符的时候,每次只读入一个数字,用char一劳永逸(char就是用来定义单个字符的,一个数字就是一个字符),或者在int类型下输入%1d来表示只读入一个数字(不这样做的话,程序会出错) 

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,d;
	scanf("%1d%1d%1d.%1d",&a,&b,&c,&d);
	printf("%d.%d%d%d",d,c,b,a);
	return 0;
} 

 错误例子:%d%d之间是默认隔开的,我们输入123.4,实际系统认为我们输入1 2 3.4

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,d;
	scanf("%d%d%d.%d",&a,&b,&c,&d);
	printf("%d.%d%d%d",d,c,b,a);
	return 0;
}

 ③使用循环,调用字符数组下标,实现字符串的逆序输出

#include<iostream>
#include<string.h>
using namespace std;

int main()
{
	char a[100];//100个元素,下标从0到99 
	cin >> a;
	
	for (int i = strlen(a)-1; i >= 0; i --)//所以长度是100-1,然后到0 
	cout << a[i];
	
	return 0;
}

(6)P5706

注意:printf可以直接指定保留几位小数,直接在%lf或者%f的百分号后面写”.x"(x为想保留的小数位数)例如保留3位为%.3lf 

#include<iostream>
using namespace std;

int main()
{
	double t;
	int n;
	cin>>t>>n;
	
	printf("%.3lf\n%d\n",t/n,n*2);
	return 0;
}

(7)P5708(sqrt函数)

注意: sqrt()函数用于”开根号“,使用需要引入头文件”#include<cmath>";

实数就是数轴上的点,包括小数;

#include<iostream>
#include<cmath>
using namespace std;

int main()
{
	double a,b,c,p,s;//a,b,c使用double的原因:题目要求为实数,实数是数轴上的点(总之包括小数) 
	cin>>a>>b>>c;
	
	p=(a+b+c)/2.0;
	s=sqrt(p*(p-a)*(p-b)*(p-c));
	printf("%.1lf",s);
	return 0;
}

 (8)P1425

①思路一:统一为分钟再加减(符合顺序结构做法)

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,d,z;
	cin>>a>>b>>c>>d;
	
	z=(c*60+d)-(a*60+b);

	cout<<z/60<<" "<<z%60;
	return 0;
}

 ②思路二:使用if,先判断再加减(分支结构做法)

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,d;
	cin>>a>>b>>c>>d;
	
	if(d<b)
	{
		d+=60;
		c-=1;
	}
	cout<<c-a<<" "<<d-b;
	return 0;
}

(9)P3954

①int()进行强制类型转换 (小坑,也可以直接输出表达式结果避开这个坑)

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,sum;
	cin>>a>>b>>c;
	
	sum=int(a*0.2+b*0.3+c*0.5);
	cout<<sum;
	return 0;
}

二、分支结构

(1)P5709

 注意:有三个坑。t为0时,肯定能吃完,且t不能作为被除数,特例特判;问剩下多少个完整的苹果,说明需要向下取整(有余数时需要加1);当能吃完且时间有剩余时,也需要进行特判,结果为负数,我们不需要输出负数,我们只需要输出0表示无剩余;

#include<iostream>
using namespace std;

int main()
{
	int m,t,s;
	cin>>m>>t>>s;
	
	if(t==0||m*t<s){//特判,这两种情况下直接输出0并结束运行
		cout<<0;
	}
	else if(s%t==0)//排除上面两种情况后,再次进行判断,是否需要向下取整
	{
		cout<<m-s/t;
	}
	else
	{
		cout<<m-(s/t+1);
	}
		
	return 0;
}

②优化(使用了三目运算符,m=s%t==0?m-s/t:m-(s/t+1);,先进行红色部分的运算,先判断s%t是否等于0,如果等于,则执行:左边的m-s/t;如果不等于,则执行:右边的m-(s/t+1)

#include<iostream>
using namespace std;

int main()
{
	int m,t,s;
	cin>>m>>t>>s;
	
	if(t==0||m*t<s){
		cout<<0;
	}
	else//合并判断是否需要向下取整的情况的计算
	{
	    m=s%t==0?m-s/t:m-(s/t+1);三目运算符
	    cout<<m;
	}
	return 0;
}

(2)P5710

①比较复杂的使用与(&&)和或(||)暴力解题

#include<iostream>
using namespace std;

int main()
{
	int x;
	bool a=0,b=0,c=0,d=0;
	cin>>x;
	
	if(x%2==0&&(x>4&&x<=12))
	{
		a=1;
	}
	
	if(x%2==0||(x>4&&x<=12))
	{
		b=1;
	}
	
	if((x%2==0&&(x<=4||x>12))||(x%2!=0&&x>4&&x<12))
	{
		c=1;
	}
	
	if(x%2!=0&&(x<=4||x>12))
	{
		d=1;
	}
	
	cout<<a<<" "<<b<<" "<<c<<" "<<d;
	
	return 0;
}

 注意:bool变量只有两个结果,true/false(1/0),一定要进行初始化,否则会随机赋值0/1,结果就不确定了;有一个小坑,x是大于4,小于等于12的。取反的话就是x小于等于4,大于12;

(3)P5711(闰年判断)

注意:闰年判断:能被400整除或者能被4整除且不被100整除。

#include<iostream>
using namespace std;

int main()
{
	int n=0;
	cin>>n;
	
	if(n%400==0||n%4==0&&n%100!=0)n=1;
	else n=0;
	cout<<n;
	
	return 0;
}

②优化(使用三目运算符进行判断) 

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	
	cout<<(n%400==0||n%4==0&&n%100!=0)?1:0;
	
	return 0;
}

(4)P5712

很简单,有两种输入输出的方法,用printf更方便 

#include<iostream>
using namespace std;

int main()
{
	int x;
	cin>>x;
	
	if(x==1||x==0)cout<<"Today, I ate "<<x<<" apple."<<endl;//printf("Today, I ate %d apple.",x);
	else cout<<"Today, I ate "<<x<<" apples."<<endl;//printf("Today, I ate %d apples.",x);
	
	return 0;
}

 (5)P5715

①暴力解法,使用一个中间变量交换变量的值 

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,k;
	cin>>a>>b>>c;
	
	if(a<b){k=a;a=b;b=k;}
	if(a<c){k=a;a=c;c=k;}
	if(b<c){k=b;b=c;c=k;}
	cout<<c<<" "<<b<<" "<<a;
	return 0;
}

 ②使用swap()函数交换两个变量的数据

#include<iostream>
using namespace std;

int main()
{
	int a,b,c;
	cin>>a>>b>>c;
	
	if(a<b)swap(a,b);
	if(a<c)swap(a,c);
	if(b<c)swap(b,c);
	cout<<c<<" "<<b<<" "<<a;
	return 0;
}

(6)P5716(月份天数及闰年)

解题思路:大月1,3,5,7,8,10,12永远是31天,小月4,6,9,11永远是30天,平月2月需要进行特判(闰年时为29天,不是闰年的话就是28天)

#include<iostream>
using namespace std;

int main()
{
	int y,m;
	cin>>y>>m;
	
	if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)cout<<31;
	else if(m==4||m==6||m==9||m==11)cout<<30;
	else if(m==2)
	{
		if(y%400==0||y%4==0&&y%100!=0)cout<<29;
		else cout<<28;
	}
	return 0;
}

(7)P1085

 ①只用if,暴力解题

#include<iostream>
using namespace std;

int main()
{
	int a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7,maxx=-1,day;
	cin>>a1>>b1>>a2>>b2>>a3>>b3>>a4>>b4>>a5>>b5>>a6>>b6>>a7>>b7;
	
	if(a1+b1>8&&a1+b1>maxx){maxx=a1+b1;day=1;}
	if(a2+b2>8&&a2+b2>maxx){maxx=a2+b2;day=2;}
	if(a3+b3>8&&a3+b3>maxx){maxx=a3+b3;day=3;}
	if(a4+b4>8&&a4+b4>maxx){maxx=a4+b4;day=4;}
	if(a5+b5>8&&a5+b5>maxx){maxx=a5+b5;day=5;}
	if(a6+b6>8&&a6+b6>maxx){maxx=a6+b6;day=6;}
	if(a7+b7>8&&a7+b7>maxx){maxx=a7+b7;day=7;}
	
	cout<<day;
	
	return 0;
}

② 使用循环优化

#include<iostream>
using namespace std;

int main()
{
	int a,b,maxx=-1,day;
	for(int i=1;i<=7;i++)
	{
		cin>>a>>b;
		if(a+b>8&&a+b>maxx)
		{
			maxx=a+b;
			day=i;
		}
	}
	cout<<day;
	
	return 0;
}

(8)P1909

 ①暴力解题,比较三个数里的最小值,参考前面的解题方法

#include<iostream>
using namespace std;

int main()
{
	int n,a1,a2,b1,b2,c1,c2,num1,num2,num3,minn=10000001;
	cin>>n>>a1>>a2>>b1>>b2>>c1>>c2;
	
	num1=n%a1==0?n/a1:n/a1+1;num1*=a2;
	num2=n%b1==0?n/b1:n/b1+1;num2*=b2;
	num3=n%c1==0?n/c1:n/c1+1;num3*=c2;
	if(num1<minn)minn=num1;
	if(num2<minn)minn=num2;
	if(num3<minn)minn=num3;
	cout<<minn;
	
	return 0;
}

②优化

#include<iostream>
using namespace std;

int main()
{
	int n,a1,a2,num,minn=1000000001;
	cin>>n;
	for(int i=0;i<3;i++)
	{
		cin>>a1>>a2;
		num=n%a1==0?n/a1:n/a1+1;
		num*=a2;
		if(num<minn)swap(num,minn);
	}

	cout<<minn;
	
	return 0;
}

 (9)P1422(四舍五入)

①使用printf()输出浮点数,如果你规定了精确到小数点后几位,那么它会自动四舍五入

#include<iostream>
using namespace std;

int main()
{
	int a;
	double price;
	cin>>a;
	
	if(a<=150){
		price=a*0.4463;
	}else if(a>=151&&a<=400){
		price=150*0.4463+(a-150)*0.4663; 
	}else{
		price=150*0.4463+250*0.4663+(a-400)*0.5663;
	}
	printf("%.1lf",price);
	
	return 0;
}

② 也可以通过计算四舍五入

#include<iostream>
using namespace std;

int main()
{
    int a=0;
    double b=0;
    cin>>a;
    
    if(a<=150){
        b=a*0.4463;
    }else if(a>=151&&a<=400){
        b=150*0.4463+(a-150)*0.4663;
    }else{
        b=150*0.4463+(400-150)*0.4663+(a-400)*0.5663;
    }
    b=int((b*10)+0.5)/10.0;//四舍五入到小数点后一位
    cout<<b;
    return 0;
}

(10)P1424

解题思路:进行n次循环,在循环内进行两种判断,非周末日时我们进行sum的累加,周末日时进行x的累加或重置(只有周日时进行重置,其他时候累加) 

#include<iostream>
using namespace std;

int main()
{
	int x,n,sum=0;
	cin>>x>>n;
	for(int i=1;i<=n;i++)
	{
		if(x!=6&&x!=7)sum+=250;
		if(x==7)x=1;
		else x++;
	}
	cout<<sum;
	return 0;
}

 这道题就用循环解,用if语句解太麻烦复杂

(11)P1888(约法,辗转相除法求最大公约数)

解题思路:辗转相除法求最大公约数(约分)

前提:m为被除数,n为除数(即m/n);

②若m%n==0,那么n就是最大公约数;

③若m%n!==0,那么我们使用辗转相除法进行计算。m%n==c(c是余数,且不等于0),我们把n当作被除数,把c当作除数继续计算n%c==d(d是余数,如果d等于0,那么计算结束,此表达式的除数为我们所求的最大公约数,如果d不等于0,那么我们继续辗转相除法,把除数当作被除数,把余数当作除数,一直计算到余数为0时停止) 

图解:

以下是代码实现: 

#include<iostream>
using namespace std;

int main()
{
	int a,b,c,aa,cc,k;//k用来存放余数 
	cin>>a>>b>>c;
	
	if(a>b)swap(a,b);
	if(a>c)swap(a,c);
	if(b>c)swap(b,c);//到这里,a为最小边,c为最大边 
	
	//接下来用辗转相除法求最大边和最小边的最大公约数(说白了就是进行两者的约分)
	aa=a;cc=c;//拷贝
	while(aa%cc!=0)
	{
		k=aa%cc;
		aa=cc;
		cc=k;
	}
		cout<<a/cc<<"/"<<c/cc; 
	return 0;
}

(12)P4414

#include<iostream>
using namespace std;

int main()
{
	int a,b,c;
	char ch;
	cin>>a>>b>>c;
	
	if(a>b)swap(a,b);
	if(a>c)swap(a,c);
	if(b>c)swap(b,c);
	
	for(int i=0;i<3;i++)
	{
		cin>>ch;
		if(ch=='A')cout<<a<<" ";
		if(ch=='B')cout<<b<<" ";
		if(ch=='C')cout<<c<<" ";
	}
	
	return 0;
}

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值