题解 P2026 【求一次函数解析式】
WanderingTrader
·
·
题解
这道题本身是一道数学题,大概是初二水平,能用数学方法做出来,计算机自然可以。
题目分析
首先我们用数学方法来做一下这道题。
已知:某一次函数过(x_1,y_1),(x_2,y_2)两点,求函数解析式。
解:
设这个函数解析式为y=kx+b(k\ne 0),
由题意得\begin{cases}kx_1+b=y_1①\\kx_2+b=y_2②\end{cases}
当$x_1,y_1,x_2,y_2$都为给定的已知数时,确定$k$和$b$只是计算的问题,全部交给计算机。
### 代码
看起来,这道题我们已经做完了。
~~结果重读了一遍题目就打脸了~~
这里还要做分数处理。
初始化:
```cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("y=");
return 0;
}
```
首先我们用变量$p,q$存放$k$的分子和分母(即将$k$表示成$\dfrac{p}{q}$):
```cpp
int p = y1 - y2,q = x1 - x2;
```
如果$p,q$异号(此时$k<0$),输出一个负号:
```cpp
if(p * q < 0) printf("-");
```
接下来是分数化简,写一个gcd:
```cpp
int gcd(int x,int y)
{
if(x < 0) x = -x;
if(y < 0) y = -y;
if(x < y) swap(x,y);
if(!y) return x;
return gcd(y,x % y);
}
```
为了不改变$p,q$的值,负数在gcd中处理。
把$p,q$同时除以$\gcd(p,q)$:
```cpp
int k = gcd(p,q);
p /= k;
q /= k;
```
此时如果$\left\vert q\right\vert=1$,直接输出$\left\vert p\right\vert$即可:
```cpp
if(abs(q) == 1)
{
if(abs(p) == 1) printf("x");
else printf("%dx",abs(p));
}
```
当然,系数绝对值为1的还是要处理下。
否则直接输出分数$\dfrac{p}{q}$即可:
```cpp
else
printf("%d/%d*x",abs(p),abs(q));
```
现在一次项系数处理完毕,开始处理常数项。
把常数项设为$\dfrac{a}{b}$:
```cpp
int a = y1 * q - p * x1,b = q;
```
为了方便处理,我们进行了通分,不过计算依然很简单。
如果常数项为$0$,不用输出了:
```cpp
if(!a) return 0;
```
然后是老规矩,先判断正负:
```cpp
if(a * b < 0) printf("-");
else printf("+");
```
然后分数化简:
```cpp
int m = gcd(a,b);
a /= m;
b /= m;
```
最后做分母为1的特殊处理:
```cpp
if(abs(b) == 1)
printf("%d\n",abs(a));
else
printf("%d/%d",abs(a),abs(b));
```
因为是常数项,这里不用做分子为1的处理了。
全部代码:
```cpp
#include <bits/stdc++.h>
using namespace std;
int gcd(int x,int y)
{
if(x < 0) x = -x;
if(y < 0) y = -y;
if(x < y) swap(x,y);
if(!y) return x;
return gcd(y,x % y);
}
int main()
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("y=");
int p = y1 - y2,q = x1 - x2;
if(p * q < 0) printf("-");
int k = gcd(p,q);
p /= k;
q /= k;
if(abs(q) == 1)
{
if(abs(p) == 1) printf("x");
else printf("%dx",abs(p));
}
else
printf("%d/%d*x",abs(p),abs(q));
int a = y1 * q - p * x1,b = q;
if(!a) return 0;
if(a * b < 0) printf("-");
else printf("+");
int m = gcd(a,b);
a /= m;
b /= m;
if(abs(b) == 1)
printf("%d\n",abs(a));
else
printf("%d/%d",abs(a),abs(b));
return 0;
}
```
其实只要学过一次函数,代码不难写出,关键在于特殊情况的判断。在测试过程中,笔者发现,题目给的数据并不强(很多特殊数据没有给到),导致一些看似正确的代码其实是错误的,我们写代码的时候要时刻牢记每一个判断要点,避免在正式比赛,数据加强后产生不必要的失分。
$\mathrm{The\ End.}