入门语法题目精讲
P5710数的性质
对于本题,我们定义两个bool类型的变量分别代表数字是否满足性质1和2
即:
bool is1=x%2==0;
bool is2=(x>4 && x<=12);
这样两个变量就可以代表是否满足性质1跟2了
那么小A其实就是两个值\(&&\)的结果
Uim就是两个值\(||\)的结果
小B就是会比较麻烦,就是第一个和第二个取\(!\)之后再\(&&\)的结果\(||\)上第一个取\(!\)和第二个\(&&\)之后的结果,文字有点难以理解,主要看代码
正妹就是两个同时取\(!\)之后再\(&&\)的结果
代码如下
#include<iostream>
using namespace std;
int main()
{
int x;
cin>>x;
bool is1=x%2==0;
bool is2=(x>4 && x<=12);
bool ans1=is1 && is2;
bool ans2=is1 || is2;
bool ans3=(is1 && (!is2)) || ((!is1) && is2) ;
bool ans4=(!is1) && (!is2);
cout<<ans1<<" "<<ans2<<" "<<ans3<<" "<<ans4;
return 0;
}
P5715三位数排序
本题并不难,需要注意的点是要学会交换两个变量的值,具体过程如下:
int a,b;
cin>>a>>b;
int t=a;
a=b;
b=t;
cout<<a<<b;
在上述代码,我们用了第三个变量存下了a的值,这样在a赋成b的值之后还能通过t将原本a的值赋给b,从而达到交换值的效果
如果没有这个第三变量存a的值,那么在把a赋成b的值之后原本a的值就消失了,两个变量的值都变成了原本b的值,从而无法实现交换的效果
那么在学会了交换之后,这道题就是把最大的值换到最后,中间的值换到中间,最小值换到前面就行了,实现如下:
#include<iostream>
using namespace std;
int main()
{
int a,b,c;
cin>>a>>b>>c;
if(a>b)
{
int t=a;
a=b;
b=t;
}
if(a>c)
{
int t=a;
a=c;
c=t;
}
if(b>c)
{
int t=b;
b=c;
c=t;
}
cout<<a<<" "<<b<<" "<<c;
return 0;
}
上述代码中,一开始在a>b时我们交换两值,所以此时a一定小于等于b,同理又在a>c时交换两值,又保证了a一定小于等于b,所以此时a一定是最小的
此时再用一样的方法保证了b小于等于c,所以三个数一定是排好序的
需要注意的时,如果你写成了:
#include<iostream>
using namespace std;
int main()
{
int a,b,c;
cin>>a>>b>>c;
if(a>b)
{
int t=a;
a=b;
b=t;
}
if(b>c)
{
int t=b;
b=c;
c=t;
}
if(a>c)
{
int t=a;
a=c;
c=t;
}
cout<<a<<" "<<b<<" "<<c;
return 0;
}
那么你将无法通过本题,为什么呢?
我们推一下,刚开始第一个if保证了a小于等于b,第二个if保证了b小于等于c,第三个if保证了a小于等于c,看似没有问题
但是在第二个if的时候,b的值有可能进行了交换,那么b的值就变了,此时a就不一定小于等于b,那么就不一定满足题意了,所以会发生错误
大家在设计算法的时候一定要注意这种逻辑错误
此外,我们补充一个函数\(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<<a<<" "<<b<<" "<<c;
return 0;
}
P1424 小鱼的航程(改进版)
首先,考虑每七天是一个周期,每个周期游1250,所以答案完整周期部分是\(1250*(n/7)\)
然后考虑从当前天到第一个周一的不满一周的天数,显然当前天到到第一个周一的天数为\(8-x\),由于周末无用,所以游的天数是(6-x),小于0的时候按0处理
然后再考虑最后不到一周的天数,先减去前面到第一个周一的天数,即\(8-x\),然后就是最后不满一周的天数了,如果超过五天就说明存在周末,按五天计算即可
所以三部分相加便是答案,实现如下:
#include<iostream>
using namespace std;
int main()
{
int x,n;
cin>>x>>n;
int pre=6-x;
if(pre<0)
{
pre=0;
}
n-=8-x;
int back=n%7;
if(back>5)
{
back=5;
}
int ans=pre*250+n/7*1250+back*250;
cout<<ans;
return 0;
}
在这里,我们再学两个新的函数,分别是\(max()\)和\(min()\)
两个函数的参数都会有两个,然后如同名字一样,\(max(x,y)\)会得到\(x\)和\(y\)中较大的一个
同理,\(min\)函数会得到较小的一个
在本题中,我们在\(pre\)小于0的时候设成0,其实就是取0和\(pre\)中较大的那个值
\(back\)则是5和\(back\)中较小的那个值
所以,本题的代码可以改写成:
#include<iostream>
using namespace std;
int main()
{
int x,n;
cin>>x>>n;
int pre=max(0,6-x);
n-=8-x;
int back=min(n%7,5);
int ans=pre*250+n/7*1250+back*250;
cout<<ans;
return 0;
}
代码就简短了许多
P1909 [NOIP 2016 普及组] 买铅笔
对于本题,要花费最少,所以我们只需要分别算出三种包装所需要的价钱,然后输出最小值就行了
那么唯一的问题就是怎么算出来每种的价钱
显然只需要算出每种包装需要多少,然后乘价格就行了
但是我们发现如果直接除,在不能除尽的情况下,c++的整除会是向下取整的,所以我们是差一包的,所以要特判有余数的时候多一包
如果只是这样那么这道题根本不算经典!
在这里,我们要讲的其实是向上取整
在c++中,a除以b向上取整可以写成这样:
int x=(a+b-1)/b;
为什么这样是向上取整呢?
让我们来拆解一下
我们先设\(a=b*t+m\)
那么上述式子就变成了\((b*t+m+b-1)/b\)
如果\(m\)等于0
那么就是\((b*t+b-1)/b\) 显然,向下取整之后会是t
那么就跟直接整除是一样的,都是t
如果\(m\)大于0
原式可以写成\((b*(t+1)+m-1)/b\)
由于\(m\)是\(a/b\)的余数,所以必定小于\(b\),那么\(m-1\)必定小于\(b\),所以向下取整之后得到\(t+1\)
所以在在\(a/b\)余零的时候该式子得到\(t\),其余情况得到\(t+1\),我们就实现了向上取整的效果
所以,本题代码实现如下:
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int num,v;//num为每包数量,v为价格
cin>>num>>v;
int ans1=(n+num-1)/num*v;//算出第一种所需价钱
cin>>num>>v;//输入第二种的数量和价格
int ans2=(n+num-1)/num*v;//算出第二种所需的价钱
cin>>num>>v;//同上
int ans3=(n+num-1)/num*v;
cout<<min(ans1,min(ans2,ans3));//输出最小的
return 0;
}
P5705 【深基2.例7】数字反转
可以发现这道题前面的几道题都是字符变量的练习题,这道题确实浮点数
但其实,这道题也是字符变量的练习题
本题的关键点在于我们不能把输入看成一个浮点数,一个不小于一百,小于一千的一位浮点数,其实是由四个数字和一个小数点组成
所以我们把输入看成五个字符,然后倒着输出就行
实现如下:
#include<iostream>
using namespace std;
int main()
{
char a,b,c,d,e;
cin>>a>>b>>c>>d>>e;
cout<<e<<d<<c<<b<<a;
return 0;
}

浙公网安备 33010602011771号