dxedxy 2024-02-01 17:02 采纳率: 0%
浏览 4

6107 一元二次方程

具体查看网址:
https://oj.aicoders.cn/
中的第6107题。
谢谢!!

  • 写回答

1条回答 默认 最新

  • VRJerry 2024-02-01 22:49
    关注

    这个题目去给的网址上看了下,其实整理一下除了输出麻烦点,其他的只是看着复杂:
    1、判断一元二次方程是否存在根(根据求根公式Δ=b^2-4ac),不存在则输出NO
    2、有根的情况下,对最大的根输出,最大的根一定是x=(-b+√Δ)/2a,也就是对这个式子根据情况进行处理:
    (1)如果根号可以打开,也就是分子、分母都是整数的情况:如果能整除,则输出整数;如果不能整除,输出一个最简分数(就是类似8/6要化简成4/3)
    (2)如果根号不可以完全打开的情况下,那么我们可以假设Δ=ddδ,则,我们可以把x表达式转换为:x=(-b/2a)+(d/2a)√δ=q1+q2√δ的形式,对q1、q2最后表达的要求与(1)中一样的,要是整数或者最简分数。其中如果q2是1不需要显示。
    因此,这个题目就涉及三个部分考察:
    1、根据求根公式求得x表达式各部分的值
    2、对x各部分进行化简(约分)
    3、根据不同情况进行输出

    我这里给出一个按照上述思路解答的一个样例代码(c++环境下),输出结果见图。部分函数如果要转c可能需要一些调整,但应该不会很多。打印部分就莽了,c++弄字符串不熟悉,就不去琢磨输出的问题了。。。无法提交,就用题目里公开的例子试了一下

    img

    
    #include <iostream>
    using namespace std;
    
    void IRRationalPrint(long r_numerator, long r_denominator, long i_numerator, long i_denominator, long res)//打印无理数结果
    {
    //纯if嵌套输出不同情况了,没去考虑用根据条件形成不同字符串的形式,或者去处理格式化文本的条件等方式。
        if (r_numerator == 0)
        {
            if (i_denominator == 1)
                i_numerator == 1 ? printf("sqrt(%ld)\n", res) : printf("%ld*sqrt(%ld)\n", i_numerator, res);
            else
                i_numerator == 1 ? printf("sqrt(%ld)/%ld\n", res, i_denominator):printf("%ld*sqrt(%ld)/%ld\n",  i_numerator, res, i_denominator);
            return;
        }
    
    
        if (r_denominator == 1)
        {
            if(i_denominator==1)
                i_numerator == 1 ? printf("%ld+sqrt(%ld)\n", r_numerator, res):printf("%ld+%ld*sqrt(%ld)\n", r_numerator, i_numerator, res);
            else
                i_numerator == 1 ? printf("%ld+sqrt(%ld)/%ld\n", r_numerator, res, i_denominator):printf("%ld+%ld*sqrt(%ld)/%ld\n", r_numerator, i_numerator, res,i_denominator);
        }
        else
        {
            if (i_denominator == 1)
                i_numerator == 1 ? printf("%ld/%ld+sqrt(%ld)\n", r_numerator, r_denominator, res) : printf("%ld/%ld+%ld*sqrt(%ld)\n", r_numerator, r_denominator, i_numerator, res);
            else
                i_numerator == 1 ? printf("%ld/%ld+sqrt(%ld)/%ld\n", r_numerator, r_denominator, res, i_denominator) : printf("%ld/%ld+%ld*sqrt(%ld)/%ld\n", r_numerator, r_denominator, i_numerator, res, i_denominator);
        }
    }
    
    void RationalPrint(long numerator, long denominator)//打印有理结果
    {
        if (denominator == 1)
            printf("%ld\n", numerator);
        else
            printf("%ld/%ld\n", numerator, denominator);
    }
    
    void simplestRational(long& numerator, long& denominator)//对分子分母进行简化,并且修改到原来值上去
    {
        if (numerator == 0)
        {
            numerator = 0;
            denominator = 1;
            return;
        }
    
        long nm, dn;//存储无符号的分子分母;
        bool isNeg=false;//存储是同号还是异号;
        isNeg = ((numerator ^ denominator) < 0);
        nm = abs(numerator);
        dn = abs(denominator);
        long gcd = nm > dn ? dn : nm;//等于一个min函数,给最小值。gcd留最大公约数
        while (gcd > 1)//找最大公约数用于化简
        {
            if (nm % gcd == 0 && dn % gcd == 0)
                break;
            gcd--;
        }
        denominator = dn / gcd;
        numerator = nm / gcd;
        if (isNeg)
            numerator = -numerator;
    }
    
    bool isDeltaRational(long delta,long &intPart, long &resPart)//引用传递两个参量,以便修改主函数中的对应变量
    {
        long ddelta;
        ddelta = (long)sqrt(delta);//如果是C语言需要用mathf相关的,以及使用相关头文件
        if (ddelta * ddelta == delta)//判断是否能开根号成整数
        {
            intPart = ddelta;//引用过来的,所以直接修改主函数里的值
            resPart = 1;//开完了,剩下根号1
            return true;
        }
        else
        {
            for (long i = ddelta; i > 1; i--)
            {
                if (delta % (i * i) == 0)//如果找到了一个最大的平方数能够整除,就可以结束循环了,如果循环结束时候没找到,那就说明已经是不能化简的了
                {
                    intPart = i;
                    resPart = delta / (i * i);
                    return false;
                }
            }
            //不能化简,返回应有值。
            intPart = 1; resPart = delta;
            return false;
        }
        
    }
    
    
    int main()
    {
        int T, M;    //方程数和系数绝对值上限(M好像没什么用)
        int a, b, c;//abc都是在1000以内
        long delta;//判别式b^2-4ac,考虑b^2>65535是可能的,就用了long,实际上32位整数也不会超。
        scanf_s("%d %d", &T, &M);
    
        for (int i = 0; i < T; i++)//T个方程,对每一个逐一处理
        {
            scanf_s("%d %d %d", &a, &b, &c);//C语言请使用scanf即可,此处C++环境所以用了这个
            delta = b * b - 4 * a * c;//判别式计算
            if (delta < 0)//无实数根,输出NO进行下一个方程运算就行
            {
                printf("NO\n");
                continue;
            }
    
            long int_part=1,res_part=1;//res_part是用于保留如果判别式开根号不成功的话,剩余的值(应该是1或者某个最简的根号下的数),int_part用于化简后根号外的整数部分
            if (isDeltaRational(delta, int_part, res_part))//返回true就是有理数,返回false就是个无理数
            {
                long nmrt = -b + int_part;
                long dnmnt = 2 * a;
                simplestRational(nmrt, dnmnt);
                RationalPrint(nmrt, dnmnt);
            }
            else
            {
                long r_part=-b;
                long dnmntr = 2 * a, dnmnti = 2 * a;//因为约分后可能不一样,所以分两个,r是有理数,i是无理数
                simplestRational(r_part, dnmntr);
                simplestRational(int_part, dnmnti);//约分也不涉及最简的根号了,只涉及外面的这个数
                IRRationalPrint(r_part, dnmntr, int_part, dnmnti, res_part);
            }
        }
    }
    
    评论

报告相同问题?

问题事件

  • 创建了问题 2月1日

悬赏问题

  • ¥20 如何再GIS用海岸线建立缓冲区
  • ¥15 codeblock遇到问题了,求帮助😭
  • ¥15 Qt6.8.0加载网页MSVC2022
  • ¥15 360浏览器m2的这个值
  • ¥15 国内有哪些厂商做automlops的?
  • ¥15 skynet pb mysql
  • ¥15 笔记本外接显示器分辨率太低各种方法都用过了调不高
  • ¥15 Redstone R0697-F00 D2020 交换机 OS
  • ¥50 H5+js 动态数字画廊怎么做?
  • ¥20 外向内全景图像拼接相关项目和论文咨询