郑轻OJ题解

 

 

# oj刷题知识点

### 1005:整数幂

1.输出格式中的转换字符串

%c 按字符型输出字符串

%d 按十进制整数输出带符号整数

%f 按小数输出浮点型整数,默认输出6位小数

2.输出格式中的宽度修饰符

如%md:输出时默认右对齐,m代表宽度,数据列不足m列的左补空格,超过m列按照实际位数输出

​ %-md:其中“-“表示左对齐

```c
#include <stdio.h>

int main()
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
printf("%-9d%-9d%-9d\n",a,a*a,a*a*a);
printf("%-9d%-9d%-9d\n",b,b*b,b*b*b);
printf("%-9d%-9d%-9d\n",c,c*c,c*c*c);
return 0;
}
```

![image-20201117115456900](C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20201117115456900.png)

## 1008:美元与人民币

```c
#include<stdio.h>

int main()
{
double a;
scanf("%lf",&a);
printf("%.2lf",a*6.5573);
return 0;
}
```

控制小数位数就是通过输出格式说明符来规定的。

举例说明如下:

```
float f1=3.1415926;
float f2=1234.1415926;
float f3=124.1;
printf("%3.4f", f1); // 输出结果为:_ _ 3.1416 ( _ 表示空格)
printf("%3.4f", f2); // 输出结果为:1234.1416
printf("%3.4f", f3); // 输出结果为:124.1000
```

printf("%3.4f", f);中的3是控制f的整数部分按3位的固定位宽输出;4是按四舍五入的准则保留4位小数。

注:如果整数部分不足3位,则在前面补空格,超过3位,则按实际位数输出;如果小数部分不足4,则在后面补0

```c
printf("%.nlf",value); //表示保留n位小数
printf("%.*f",n,value); // n表示小数的位数,value表示结果
printf("%m.nlf",value); //表示控制宽度为m,保留n为小数,靠右对齐
printf("%-m.nlf",value); //表示控制宽度为m,保留n为小数,靠左对齐
//当控制宽度小于数值的位数时,将以实际数值宽度为准
printf("%.lf",value); //表示保留整数
```

## 1013:求两点的距离

###### C语言math

###### #include<math.h>

开平方使用sqrt()函数

```cpp
abs -- 绝对值
acos -- 反余弦
acosh -- 反双曲余弦
asin -- 反正弦
asinh -- 反双曲正弦
atan2 -- 两个参数的反正切
atan -- 反正切
atanh -- 反双曲正切
base_convert -- 在任意进制之间转换数字
bindec -- 二进制转换为十进制
ceil -- 进一法取整
cos -- 余弦
cosh -- 双曲余弦
decbin -- 十进制转换为二进制
dechex -- 十进制转换为十六进制
decoct -- 十进制转换为八进制
deg2rad -- 将角度转换为弧度
exp -- 计算 e(自然对数的底)的指数
expm1 -- 返回 exp(number) - 1,甚至当number 的值接近零也能计算出准确结果
floor -- 舍去法取整
fmod -- 返回除法的浮点数余数
getrandmax -- 显示随机数最大的可能值
hexdec -- 十六进制转换为十进制
hypot -- 计算一直角三角形的斜边长度
is_finite -- 判断是否为有限值
is_infinite -- 判断是否为无限值
is_nan -- 判断是否为合法数值
int -- 求一个数接近它的最小整数
_value -- 组合线性同余发生器
log10 -- 以 10为底的对数
log1p -- 返回 log(1 + number),甚至当number 的值接近零也能计算出准确结果
log -- 自然对数
max -- 找出最大值
min -- 找出最小值
mt_getrandmax -- 显示随机数的最大可能值
mt_rand -- 生成更好的随机数
mt_srand -- 播下一个更好的随机数发生器种子
octdec -- 八进制转换为十进制
pi -- 得到圆周率值
pow -- 指数表达式
rad2deg -- 将弧度数转换为相应的角度数
rand -- 产生一个 随机整数
round -- 对浮点数进行四舍五入
sin -- 正弦
sinh -- 双曲正弦
sqrt -- 平方根
srand -- 播下随机数发生器种子
tan -- 正切
tanh -- 双曲正切
```

### 详细用法

```c
#include <math.h>
double sin(double arg);
返回arg的正弦值,arg单位为弧度。
#include <math.h>
double cos(double arg);
返回arg的余弦值,arg单位为弧度。
#include <math.h>
double tan(double arg);
返回arg的正切值,arg单位为弧度。
#include <math.h>
double asin(double arg);
返回arg的反正弦值sin-1(x),值域为[-pi/2,pi/2],其中变元范围[-1,1]。
#include <math.h>
double acos(double arg);
返回arg的反余弦值cos-1(x),值域为[0,pi],其中变元范围[-1,1]。
#include <math.h>
double atan(double arg);
返回arg的反正切值tan-1(x),值域为[-pi/2,pi/2]。
#include <math.h>
double atan2(double a, double b);
返回a/b的反正切值tan-1(a/b),值域为[-pi,pi]。
#include <math.h>
double sinh(double arg);
返回arg的双曲正弦值。
#include <math.h>
double cosh(double arg);
返回arg的双曲余弦值。
#include <math.h>
double tanh(double arg);
返回arg的双曲正切值。
#include <math.h>
double exp(double arg);
返回幂函数ex。
#include <math.h>
double log(double arg);
返回自然对数ln(x),其中变元范围arg > 0。
#include <math.h>
double log10(double arg);
返回以10为底的对数log10(x),其中变元范围arg > 0。
#include <math.h>
double pow(double x, double y);
返回x的y次幂,如果x=0且y<=0或者如果x<0且y不是整数,那么产生定义域错误。
#include <math.h>
double sqrt(double arg);
返回arg的平方根,其中变元范围arg>=0。
#include <math.h>
double ceil(double arg);
返回不小于arg的最小整数。
#include <math.h>
double floor(double arg);
返回不大于arg的最大整数。
#include <math.h>
double fabs(double arg);
返回arg的绝对值|x|。
#include <math.h>
double ldexp(double num, int exp);
返回num * 2exp。
#include <math.h>
double frexp(double num, int *exp);
把num分成一个在[1/2,1)区间的真分数和一个2的幂数。将真分数返回,幂数保存在*exp中。如果num等于0,那么这两部分均为0。
#include <math.h>
double modf(double num, double *i);
把num分成整数和小数两部分,两部分均与num有同样的正负号。函数返回小数部分,整数部分保存在*i中。
#include <math.h>
double fmod(double a, double b);
返回除法的浮点数余数
```

## 1014:已知三边,求三角形的面积

已知三角形三边a,b,c,则

(海伦公式)(p=(a+b+c)/2)

S=sqrt[p(p-a)(p-b)(p-c)]

=sqrt[(1/16)(a+b+c)(a+b-c)(a+c-b)(b+c-a)]

=1/4sqrt[(a+b+c)(a+b-c)(a+c-b)(b+c-a)]

头文件:#include <math.h>

## 1016: 银行利率

###### 设银行1年期定期存款年利率为2.25%,存款本金为deposit元,试编程计算并输出n年后的本利之和。

```c
#include<stdio.h>
#include<math.h>
int main()
{
double n,deposit;
scanf("%lf %lf",&n,&deposit);
printf("%.6lf",deposit*pow(1.0225,n));
return 0;
}
```

pow() 函数用来求 x 的 y 次幂(次方),x、y及函数值都是double型 ,其原型为:
double pow(double x, double y);

pow()用来计算以x 为底的 y 次方值,然后将结果返回。设返回值为 ret,则 ret = x y 。

可能导致错误的情况:

- 如果底数 x 为负数并且指数 y 不是整数,将会导致 domain error 错误。
- 如果底数 x 和指数 y 都是 0,可能会导致 domain error 错误,也可能没有;这跟库的实现有关。
- 如果底数 x 是 0,指数 y 是负数,可能会导致 domain error 或 pole error 错误,也可能没有;这跟库的实现有关。
- 如果返回值 ret 太大或者太小,将会导致 range error 错误。


错误代码:

- 如果发生 domain error 错误,那么全局变量 errno 将被设置为 EDOM;
- 如果发生 pole error 或 range error 错误,那么全局变量 errno 将被设置为 ERANGE。

Math.pow(底数,几次方)
如:double a=2.0;
double b=3.0;
double c=Math.pow(a,b);
就是2的三次方是多少;
c最终为8.0;

## 1021:输出最大值

```
#include<stdio.h>
#define MAX (a > b ? a : b)
int main()
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);

printf("%d",MAX>c?MAX:c);

return 0;
}
```

条件运算符(? : )是一个三目运算符,即有三个操作数。

使用条件运算符(?:)可以实现 If else 的功能,其一般形式为:

​ 表达式1 ? 表达式2 : 表达式3

其意思是:如果表达式1为真,则运算表达式2,整个条件表达式的值为 表达式2的值;反之,则运算表达式3,整个条件表达式的值为表达式3的值。

## 宏函数

## 1037: 四则运算

```c
#include<stdio.h>
#include<math.h>
int main()
{

double s1,s2;//定义实数s1和s2
char op;//定义操作运算符op
scanf("%lf %c %lf",&s1,&op,&s2);//键盘按照要求读入三者的值
switch(op)
{
case'+':printf("%.2lf",s1+s2);break;//加号就加法运算
case'-':printf("%.2lf",s1-s2);break;//减号就减法运算
case'*':printf("%.2lf",s1*s2);break;//称号就乘法运算
case'/':
//除运算特殊一点,原因是对于0的数据处理
if(fabs(s2)>1e-10)//如果被除数不是0
printf("%.2lf",s1/s2);//进行除法运算
else //说明被除数为0
printf("Wrong input!");break;//输出错误输入提示
default:printf("Wrong input!");break;//如果不符合四则运算要求,也输出错误输入提示
}
return 0;//程序正常退出
}
```

###### if(fabs(s2)>1e-10)//如果被除数不是0

判断s2是否为0;

https://www.zhihu.com/question/430093979

得看你为什么需要做这个判断。

如果你确实就是想判断 y 是不是 0,那么是可以直接写 `y != 0` 的。如果这个 y 有别的作用,比如作为除数参与其他运算,由于 C 语言不支持无限精度计算,一个极小的非零数和零一样可能导致异常的结果,因此需要排除这种情况。

### 1061: 顺序输出各位数字

#### 输入一个不大于10的9次方的正整数,从高位开始逐位分割并输出各位数字。

```c
#include<stdio.h>
#include<math.h>
int main(){
int n,x,a;
scanf("%d",&n);
x=(int)log10(n)+1;
a=(int)pow(10,x);
while(a/10){
a/=10;
printf("%d ",n/a);
n%=a;
}
return 0;
}
```

#### 小知识点

while(a) 表示当a!=0时执行循环,其等价于while(a!=0)。
if(a) 同上。
while(!a) 表示当a=0时执行循环,其等价于while(a==0)。
if(!a) 同上。

if(j%2)continue; 表示j%2!=0时执行continue;

### 1063: 最大公约与最小公倍

输入两个正整数,输出其最大公约数和最小公倍数。

```c
#include<stdio.h>
#include<math.h>
int main()
{
int m,n,t,x,y;//定义数字一m和数字二n以及中间量t,以及x和y记录m和n的初始值
scanf("%d %d",&m,&n);//键盘输入m和n
x=m,y=n;//x和y分别记录m和n的初始值
while(m%n)//开始辗转相除,当两个数余数不为零,循环会继续这里相当于(m%n!=0)
{
t=m;//令t等于m
m=n;//新的m等于n
n=t%m;//新的n等于求余数
}
m=x/n*y;//先除后乘,防止溢出(又是一个小细节)
//这里也可以使用老方法无限循环查找
/*for(j=1;;j++)//无限循环查找最小公倍数
{
if(j%a==0 && j%b==0) break;//当j对两个数取余结果都为0,结束循环
}*/
printf("%d %d",n,m);//输出n,也即最大公因数
return 0;//程序正常退出
}
```

# 1070: 小汽车的位置

```c
**题目描述**
有一辆智能小车,最初(时间为0)的位置为(0,0),我们想知道它最后的位置。小车以每小时10公里的速度向北移动(以北为y轴正向,以东为x轴正向)。小车会受到一系列依照时间戳记排序的命令,1表示“向左转”,2表示“向右转”,3表“停止”。每个命令的前面有一个时间戳记,所以我们知道该命令是何时发出的。最后一个命令一定是“停止”。我们另外假设,这辆小车非常灵活,它可以在瞬间转弯。
以下列输入为例。小车在时间为5的时候收到一个“向左转”的命令1,在时间10收到一个“向右转”的命令2,在时间15收到一个“停止”的命令3。那么在最后时间15的时候,小车的位置将在(-50,100)。程序只要求输出小车最后的位置,第一个整数是x坐标,第二个整数是y坐标。
```

> **输入**
> 输入包含多个命令,每个命令由整数time和command组成,表示在时刻time发出命令command。command的取值范围1-3,含义如上所述。

> **输出**
> 输出占一行,包含两个整数,表示小车的最终位置。两个整数之间由空格隔开。

> **样例输入**

```c
5
1
10
2
15
3
123456
```

> **样例输出**

```c
-50 100
1
```

**看题目难度标识就知道这题不简单,但实际上综合考虑一下,去尝试建立方向坐标,这对后面图的遍历等等学习都有好处。不过不知道为啥我修改了的代码AC不了,这里还是用下我AC过的代码吧。这里的~scanf相当于scanf!=EOF,都行。根据个人喜好吧。**

```c
#include<stdio.h>

int main(){
int x=0,y=0;//设置一下小车的初始位置
int commond,time;//定义变量,命令和时间
int n=0,a=0;
while(~scanf("%d %d",&time,&commond)){//键入时间和命令,这里的~scanf等价于scanf!=EOF;
switch(n){//取模你,来定义方向
//下面是定义方向,0北——1东——2南——3
//顺时针为正,即是向右,逆时针为负,即是向左
case 0: y+=10*(time-a);break;
case 1: x+=10*(time-a);break;
case 2: y-=10*(time-a);break;
case 3: x-=10*(time-a);break;}

if(commond==3) break;//判断命令方向
if(commond==1) n-=1;
if(commond==2) n+=1;
n=(n+4)%4;//防止溢出,使你一直在0~3中,让命令能够执行下来
a=time;//记录每次的时间

}
printf("%d %d",x,y);
return 0;
}
```

## 1071: 分解质因子

> **题目描述**
> 将一个正整数分解质因数,例如,输入90,输出2 3 3 5。

> **输入**
> 输入一个正整数n(2<=n<=2000)。

> **输出**
> 从小到大输出n的所有质因子,每两个数之间空一格。

> **样例输入**

```c
20
1
```

> **样例输出**

```c
2 2 5
1
```

把一个合数分解成若干个质因数的乘积的形式,即求质因数的过程叫做分解质因数。

**其实题目要求的最后一个不能空格可以忽视,因为判题平台会自动把最后空格忽视掉,不过还是不要忽视,要学会如何处理最后一个数字后面是没有空格的情况,除了我的处理方法,还可以第一个数前面没有空格,其他数字前面都有空格,这里不作代码实现,建议自己尝试一下。关于为什么直接循环就一定是素因数,因为如果不是素因数,在前面就因为从2开始自动处理了所有不是素因数的情况了,所以不用担心循环导致出现不是素因数的问题**

## 代码

```c
#include<stdio.h>
int main()
{
int x,i;//定义未知数x和循环变量i
scanf("%d",&x);//输入未知数x
for(i=2;i>0;)//定义无限循环,素数从2开始
{
if(x%i==0)//如果x是i的整数倍
{
printf("%d",i);//输出素数i
x=x/i;
if(x==1) break;//如果x经过操作变成了1
//说明已经找完所有的素因数,输出最后一个数字不用空格
else//否则说明没有找完
{
printf(" ");//输出个空格
continue;//继续往下找
}
}
else i++;//x不是i的整数倍,i自增,继续找
}
return 0;//程序正常结束
}
```

 

上一篇:Spring源码解析 -- SpringWeb请求参数获取解析


下一篇:TypeScript 随笔2 - 泛型