解方程(有點精度問題)

#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 (遞歸求解)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章