题目
给定两个整点的坐标,求它们所在直线的函数解析式(一次函数)。
*三个样例放在一起显示, 只需要输出一行式子就行
input
3 6
2 4
3 5
2 7
3 -1
5 -2
output
y=2x
y=-2x+11
y=-1/2*x+1/2
思路
模拟题, 我的做法是用点斜式公式, 先求出斜率再带入一个点来求方程。
因为还需要显示分数且为最简。
需要考虑很多细节, 先从简单开始:
输入坐标 x1,y1,x2,y2
斜率 k 便是 (y2-y1)/(x2-x1)
显然会多次使用 y2-y1, x2-x1
, 为了减少代码复杂度也为了方便debug
这里用 a = y2-y1
, b = x2-x1
那么 k = a/b
根据点斜式 y = kx + m
也可得出 m = y1 - k*x1
(带入任意一点)
如果题目允许小数, 那到这里就结束了, 但要求使用分数且为最简:
会用分数表示的只有 k, b
故把k化为分数, 分母为 a = y2-y1
, 分子为 b = x2-x1
然后是b, 分母为 b
, 分子为 y1 * b - x1 * a
最简的话可以求出 分母b, 分子a的最大公约数, 然后分别除以最大公约数即可
数值处理好了, 接下来是如何表示正负号, 和缩写情况:
首先判断k, 当k==0
时, 应输出 y=y1 或者 y=y2
k不为0时:
- 判断是否应该在k之前加-
- 判断k是否为1, 若为1则需省略1, 只输出 y=x
- 判断k是否为分数, 若不为分数, 则输出 y=kx
, 否则输出 y=k*x
(多个*)
- 若是分数则判断分母是否为1, 若为1则只输出分子
(接下来处理m)
- 判断m之前应加什么符号
- 判断m的分母是否为1, 若为1则只输出分子
判断符号可以直接根据之前算出的小数结果来判断
代码
#include <iostream>
#include <cmath>
using namespace std;
template <typename T>
T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
//------- Coding Area ---------//
typedef long long LL;
void reduce(LL &a, LL &b) // 约分
{
LL g = gcd(a, b);
a /= g, b /= g;
}
int main()
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2 ;
LL b = x2 - x1, a = y2 - y1;
reduce(a, b);
double k = (double)a / (double)b; // y = kx + b, b = y1 - k*x1
double n = (double)y1 - k*(double)x1;
LL c = y1*b - x1*a, d = b; // 常数的分数表示
reduce(c,d);
cout << "y=";
if(k == 0) cout << y1;
else
{
if(k < 0) cout << "-";
if(a != 1 || b != 1) cout << abs(a); // 避免出现 y = 1x + 1
if(b != 1) cout << "/" << abs(b) << "*";
cout << "x";
if(n > 0) cout << "+" << abs(c);
else if( n < 0) cout << "-" << abs(c);
if(d != 1 && n != 0) cout << "/" << abs(d);
}
return 0;
}