题意:
给定方程 ,求出该方程的所有实数解
Solution:
首先对其求导,求出其导函数的所有零点,那么在导函数两个相邻的零点之间,该 次方程一定是单调的,并且最多只有一个零点,利用这个性质,我们可以二分求出这个零点。
而求出导函数的零点可以递归地做下去,直到 时,可以直接返回答案
时间复杂度
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]);
}