题解 P2026 【求一次函数解析式】

· · 题解

这道题本身是一道数学题,大概是初二水平,能用数学方法做出来,计算机自然可以。

题目分析

首先我们用数学方法来做一下这道题。

已知:某一次函数过(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.}