TIMUS1503(高阶代数方程求根)

problem

Every New Russian wants to give his children all the best. The best education, in particular. For example, Kolyan has asked the math teacher to teach his son to solve not only quadratic equations, but also cubic ones, and quaternary ones, and altogether all the equations there are. The teacher knows that equations of degrees higher than five cannot be solved in radicals in the general form. But to solve equations up to the fifth degree is also very hard. It is better to check solutions using a computer. Here your help is needed.

Input

The first line contains the degree of a polynomial N (1 ≤ N ≤ 5). In the next N + 1 lines there are integers (-100 ≤ ai ≤ 100, a0 ≠ 0). The i+2nd line contains the ith coefficient of the polynomial a0xn + a1xn–1 + … + an.

Output

Output all real roots of the polynomial taking into account their multiplicity. The roots must be given in the ascending order. The accuracy must be not less than 10–6.

Sample

input output
2
1
-2
1

1
1

solution

给定方程 anxn+an1xn1+...+a1x+a0=0 a n x n + a n − 1 x n − 1 + . . . + a 1 x + a 0 = 0 ,求出该方程的所有实数解

首先对其求导,求出其导函数的所有零点,那么在导函数两个相邻的零点之间,该n次方程一定是单调的,并且最多只有一个零点,利用这个性质,我们可以二分求出这个零点。

而求出导函数的零点可以递归地做下去,直到n=1时,可以直接返回答案。

//TIMUS1503
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"

const double eps=1e-12;
const double inf=1e12;

inline int sign(double x){
    return x<-eps ? -1 : x>eps ;
}

//coef 系数  coef[i]=a[i]
inline double get(const vector<double> &coef,double x){//将x带入方程的值
    double e=1,s=0;//e=x^i (i=0,1,2,...,n)   coef.size():n+1
    for(int i=0;i<coef.size();++i) s+=coef[i]*e,e*=x;
    return s;
}

double Find(const vector <double> &coef,int n,double lo,double hi){
    double sign_lo,sign_hi;
    if((sign_lo=sign(get(coef,lo)))==0) return lo;//lo就是零点
    if((sign_hi=sign(get(coef,hi)))==0) return hi;//hi就是零点
    if(sign_hi*sign_lo>0) return inf;//当前区间没有零点
    for(int step=0;step<100 && hi-lo>eps;++step){//标准二分
        double m=(lo+hi)*.5;
        int sign_mid=sign(get(coef,m));
        if(sign_mid==0) return m;
        if(sign_lo*sign_mid<0) hi=m;
        else lo=m;
    }
    return (lo+hi)*.5;
}

vector<double> solve(vector<double> coef,int n){
    vector<double> ret;
    if(n==1){
        if(sign(coef[1])) ret.push_back(-coef[0]/coef[1]);
        return ret;//直接求解
    }
    vector<double> dcoef(n);//求导 大小只有n(原函数是n+1)
    for(int i=0;i<n;++i) dcoef[i]=coef[i+1]*(i+1);
    vector<double> droot=solve(dcoef,n-1);
    droot.insert(droot.begin(),-inf);
    droot.push_back(inf);//开头结尾插上-inf 和inf 方便二分  关键
    for(int i=0;i+1<droot.size();++i){
        double tmp=Find(coef,n,droot[i],droot[i+1]);
        if(tmp<inf) ret.push_back(tmp);
    }
    return ret;
}

vector <double > ans;

vector <double > coef;

int main()
{
    //freopen("in.txt","r",stdin);
    //ios::sync_with_stdio(false);
    int n;
    scanf("%d",&n);
    for(int i=0;i<=n;++i){
        double tp;
        scanf("%lf",&tp);
        coef.push_back(tp);
    }
    reverse(coef.begin(),coef.end());//注意顺序看要不要逆序   coef[0]放的是x^0对应的系数

    ans=solve(coef,n);
    sort(ans.begin(),ans.end());
    for(int i=0;i<ans.size();++i){
        printf("%.6f\n",ans[i]);
    }
    return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值