luogu【P1024 一元三次方程求解】题解

题目描述

有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。

提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1,x2)之间一定有一个根。

输入输出格式

输入格式:

一行,4个实数A,B,C,D。

输出格式:

一行,三个实根,并精确到小数点后2位。

 

输入输出样例

输入样例#1:
1 -5 -4 20
输出样例#1: 
-2.00 2.00 5.00

 
  

看到大家没人打通解,那么我来发一波~~~

蒟蒻的凝视~~~


可以先看一下此题的强化版:解方程 求解一个K次函数,那么我们只需从函数图像的各个顶点二分搜索一下就可以了。 比如说如下函数:

 

我们只需在-∞到第一个顶点中搜索解,再在第一个顶点到第二个顶点中搜索……直到第n个顶点到∞中搜索解。

所以,我们只需找到此函数顶点的x值就可以了。方法很简单,只需求导,再解一下求导后的方程。

我们可以知道,对于一个

∑i=0->n aix^i = 0

的方程,n次求导后总会变成一次函数。之后再解方程,就可以一步一步把解给求出来。

代码比较奇怪,我打了一个class,希望对大家有用。

#include<bits/stdc++.h>
#define pb push_back
using   namespace   std ;
class   fun {
private :
        int   n ;
        vector   < double >   num ;
public :
        fun   ( )
        {
                n = 0 ;
                num . clear ( ) ;
        }
        int   size ( )
        {
                return   n ;
        }

        vector   < double >   getarray ( )
        {
                return   num ;
        }

        void   insert ( vector   < double >   p )
        {
                num = p ;
                n = p . size ( ) ;
        }

        void   mem ( int   p , double   e , . . . )
        {
                double   * q = & e ;
                n = p ;
                for   ( int   i = 1 ; i < = n ; i + + )
                {
                        num . pb ( * q ) ;
                        q + + ;
                }
        }

        double   operator   ( ) ( double   x )
        {
                double   ans = 0 ;
                double   xt   = 1 ;
                for   ( int   i = 0 ; i < = n - 1 ; i + + )
                {
                        ans + = xt * num [ i ] ;
                        xt * = x ;
                }
                return   ans ;
        }

        void   print ( )
        {
                for   ( int   i = 0 ; i < n ; i + + )
                {
                        if   ( i = = 0 )   cout   < <   num [ i ] ;
                        else
                        if   ( num [ i ]   ! =   0 )
                        {
                                if   ( num [ i ] < 0 )
                                        cout   < <   num [ i ]   < <   "x^" < < i ;
                                else   cout   < <   "+"   < <   num [ i ]   < <   "x^" < < i ;
                        }
                }
        }
        fun   operator   ! ( )
        {
                fun   H ;
                H . n = n - 1 ;
                for   ( int   i = 0 ; i < H . n ; i + + )
                {
                        H . num . pb ( ( i + 1 ) * num [ i + 1 ] ) ;
                }
                return   H ;
        }

        double   get_root ( double   p , double   q )
        {
                fun   f ;
                f . insert ( num ) ;
                if   ( f ( p ) * f ( q ) > 0 )   return   - 1 0 0 0 0 0 0 0 0 ;
                double   mid   =   ( p + q ) 2 ;
                while   ( p + 0 . 0 0 0 0 0 1 < q )
                {
                        if   ( f ( p ) * f ( mid ) < = 0 )   q = mid ;
                        else   p = mid ;
                        mid = ( p + q ) 2 ;
                }
                return   mid ;
        }

        double   operator   [ ]   ( int   p )
        {
                return   num [ p ] ;
        }
} ;

vector   < double >   get_all_answer ( double   s , double   e , fun   f )
{
        vector   < double >   ret ;
        vector   < double >   qw ;
        qw   =   f . getarray ( ) ;
        ret . clear ( ) ;
        if   ( qw . size ( ) < = 2 )
        {
                ret . pb ( - qw [ 0 ] q w [ 1 ] ) ;
                return   ret ;
        }
        vector   < double >   ans_list   =   get_all_answer ( s , e , ( ! f ) ) ;
        if   ( ans_list . size ( ) = = 0 )
        {
                if   ( f . get_root ( s , e ) > - 9 9 9 9 9 9 9 9 )   ret . pb ( f . get_root ( s , e ) ) ;
                return   ret ;
        }
        if   ( f . get_root ( s , ans_list [ 0 ] ) > - 9 9 9 9 9 9 9 9 )   ret . pb ( f . get_root ( s , ans_list [ 0 ] ) ) ;
        for   ( int   i = 0 ; i < ans_list . size ( ) - 1 ; i + + )
        {
                if   ( f . get_root ( ans_list [ i ] , ans_list [ i + 1 ] ) > - 9 9 9 9 9 9 9 9 )
                        ret . pb ( f . get_root ( ans_list [ i ] , ans_list [ i + 1 ] ) ) ;
        }
        if   ( f . get_root ( ans_list [ ans_list . size ( ) - 1 ] , e ) > - 9 9 9 9 9 9 9 9 )
                ret . pb ( f . get_root ( ans_list [ ans_list . size ( ) - 1 ] , e ) ) ;
        vector   < double >   RET ;
        if   ( ret . size ( ) = = 0 )   return   ret ;
        RET . pb ( ret [ 0 ] ) ;
        for   ( int   i = 1 ; i < ret . size ( ) ; i + + )
        {
                if   ( abs ( ret [ i ] - ret [ i - 1 ] ) > 0 . 0 0 0 0 1 )
                        RET . pb ( ret [ i ] ) ;
        }
        return   RET ;
}

int   main ( )
{
        fun   f ;
        vector   < double >   g ;
        int   n ;
        cin   > >   n ;
        n + + ;
        for   ( int   i = 1 ; i < = n ; i + + )
        {
                double   x ;
                cin   > >   x ;
                g . pb ( x ) ;
        }
        f . insert ( g ) ;
        double   s , e ;
        cin   > >   s   > >   e ;
        vector   < double >   ans ;
        ans   =   get_all_answer ( s , e , f ) ;
        for   ( int   i = 0 ; i < ans . size ( ) ; i + + )
                printf ( "%.5lf " , ans [ i ] ) ;
}

转载于:https://www.cnblogs.com/dgklr/p/9077553.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值