# 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;
}
```

## 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;//程序正常結束
}
```