题目

题意:

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

Solution:

首先对其求导,求出其导函数的所有零点,那么在导函数两个相邻的零点之间,该 n 次方程一定是单调的,并且最多只有一个零点,利用这个性质,我们可以二分求出这个零点。
而求出导函数的零点可以递归地做下去,直到 n = 1 时,可以直接返回答案
时间复杂度 O ( n 3 l o g )

Code:

//equ->equation
//d->delta
//s->sign
//rt->root
#include<bits/stdc++.h>
using namespace std;
typedef double D;
typedef vector<D> V;
const D inf=1e11,eps=1e-12;
V ans,equ;
int n,i;
D x;
inline int sgn(D x){
    return x<-eps?-1:x>eps;
}
D get(V equ,D x){
    D e=1,s=0;
    for (int i=0;i<equ.size();i++) s+=e*equ[i],e=e*x;
    return s;
}
D find(V equ,D l,D r){
    int sl,sr;
    if ((sl=sgn(get(equ,l)))==0) return l;
    if ((sr=sgn(get(equ,r)))==0) return r;
    if (sl*sr>0) return inf;
    for (;r-l>eps;){
        D m=(l+r)/2;
        int sm=sgn(get(equ,m));
        if (sm==0) return m;
        if (sl*sm<0) r=m;
        else l=m;
    }
    return (l+r)/2;
}
V solve(V equ,int n){
    V res;
    if (n==1){
        if (sgn(equ[1])) res.push_back(-equ[0]/equ[1]);
        return res;
    }
    V dequ(n);
    for (int i=0;i<n;i++) dequ[i]=equ[i+1]*(i+1);
    V drt=solve(dequ,n-1);
    drt.insert(drt.begin(),-inf);
    drt.push_back(inf);
    for (int i=0;i<drt.size()-1;i++){
        D ans=find(equ,drt[i],drt[i+1]);
        if (ans<inf) res.push_back(ans);
    }
    return res;
}
int main(){
    scanf("%d",&n);
    for (i=0;i<=n;i++) scanf("%lf",&x),equ.push_back(x);
    reverse(equ.begin(),equ.end());//注意逆序
    ans=solve(equ,n);
    sort(ans.begin(),ans.end());
    for (i=0;i<ans.size();i++) printf("%.6lf\n",ans[i]);
}