title: 题目
给定两个整点的坐标,求它们所在直线的函数解析式(一次函数)。
*三个样例放在一起显示, 只需要输出一行式子就行
title: input
3 6
2 4
3 5
2 7
3 -1
5 -2
title: output
y=2x
y=-2x+11
y=-1/2*x+1/2
title: 思路
模拟题, 我的做法是用点斜式公式, 先求出斜率再带入一个点来求方程。
因为还需要显示分数且为最简。
需要考虑很多细节, 先从简单开始:
输入坐标 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=0`
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 << 0;
else
{
if(k < 0) cout << "-";
if(a != 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;
}