一次函数 T1744 963字符写法

题目

给定两个整点的坐标,求它们所在直线的函数解析式(一次函数)。
*三个样例放在一起显示, 只需要输出一行式子就行
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值