#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int MaxN = 100 + 10;
const long double eps = 1e-16, INF = 1e20;
int n,sl[MaxN];long double f[MaxN][MaxN],ans[MaxN][MaxN],t;
int sgn(double x)
{
if(x<0) return -1;
if(x>0) return 1;
return 0;
}
long double calc(int v,double x)
{
long double t=1,ret=0;
for(int i=0;i<=v;i++)
{
ret+=t*f[v][i];
t*=x;
}
return ret;
}
bool erf(int v,long double st,long double en)
{
if(sgn(calc(v,st))*sgn(calc(v,en))>0) return false;
long double mid;bool kk=(sgn(calc(v,st))>=0);
while(fabs(st-en)>eps)
{
mid=(st+en)/2.0;
if(sgn(calc(v,mid))>=0)
{
if(kk) st=mid;
else en=mid;
}
else
{
if(kk) en=mid;
else st=mid;
}
}
if(kk) t=st;
else t=en;
return true;
}
void ask(int v)
{
if(v==1)
{
if( sgn(f[v][1]) ) ans[v][sl[v]=1]=-f[v][0]/f[v][1];
else sl[v]=0;
return;
}
for(int i=1;i<=v;i++) f[v-1][i-1]=f[v][i]*i;
ask(v-1);
ans[v-1][0]=-INF;ans[v-1][sl[v-1]+1]=INF;
for(int i=0;i<=sl[v-1];i++)
if(erf(v,ans[v-1][i]+eps,ans[v-1][i+1])) ans[v][++sl[v]]=t;
}
int main()
{
scanf("%d",&n);
for(int i=n;i>=0;i--) cin>>f[n][i];
ask(n);
for(int i=1;i<=sl[n];i++) cout<<ans[n][i]<<endl;
return 0;
}
題目描述:
方程: a0 * x^n + a1 * x^(n-1) + a2 * x^(n-2) + ... + an = 0
求方程在 [-10^20,10^20] 內的實數解
輸入:
第一行:一個整數n,表示最高項指數 n>=1
第二行:接下來n+1個實數數 分別表示 a0,a1,a2,a3...,an
輸出:
對於每一個解輸出一行
想法(未證明):
對於 f(x) = a0 * x^n + a1 * x^(n-1) + a2 * x^(n-2) + ... + an = 0 求拐點,對於每一段單調區間進行二分
求拐點: 求f(x)導函數 f'(x) 則 變爲求 f'(x)=0 (遞歸求解)