解一元三次方程noip2001

题目描述

有形如:ax^3+bx^2+cx^1+dx^0=0ax3+bx2+cx1+dx0=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,da,b,c,d均为实数),并约定该方程存在三个不同实根(根的范围在-100−100至100100之间),且根与根之差的绝对值\ge 1≥1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后22位。

提示:记方程f(x)=0f(x)=0,若存在22个数x_1x1​和x_2x2​,且x_1<x_2x1​<x2​,f(x_1) \times f(x_2)<0f(x1​)×f(x2​)<0,则在(x_1,x_2)(x1​,x2​)之间一定有一个根。

输入格式

一行,44个实数A,B,C,DA,B,C,D。

输出格式

一行,33个实根,并精确到小数点后22位。

输入输出样例

输入 #1复制

1 -5 -4 20

输出 #1复制

-2.00 2.00 5.00

一、枚举法

cout.precision设置小数点位数;

cout.setf(ios::fixed)以定点形式显示浮点数;

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cstdlib>
using namespace std;

int pow(int x,int n) {
	int res = 1;
	for(int i = 0; i < n; i++) res *= x;
	return res;
}

int main() {
	double x,f,a,b,c,d;
	cin >> a >> b >> c >> d;
	cout.precision(2);		//设置精度,即小数点位数 
	cout.setf(ios::fixed);		//以定点形式显示浮点数 
	for(double i = -10000; i <= 10000; x = (++i) / 100.0) {
		f = x * x * x * a + x * x * b + x * c + d;
		if(f >= -0.01 && f <= 0.01)
			cout << x << ' '; 
	}
	cout << endl; 
	return 0;
} 

二、二分法

记方程为f(x) = 0,若存在两个不同的数x_{1}x_{2},且f(x_{1}) * f(x_{2}) < 0,则在(x_{1}x_{2})之间一定有一个根;

当已知区间(a,b)内有一个根时,可用二分法求解,若区间(a,b)内有根,则必有f(a)*f(b) < 0。重复执行一下过程:

令m = (a + b) / 2;

  1. 若 a + 0.000 1 > b 或 f(m) = 0,则可以确定根为m,并退出过程;
  2. 若 f(a) * f(m) < 0,则必有 f(m) * f(a) < 0 根在区间(a,m)中,故对区间重复该过程;
  3. 若 f(a) * f(m) < 0,则必有 f(m) * f(b) < 0 根在区间(m,b)中,对区间重复该过程;

执行完毕,就可以得到精确到0.000 1的根;

   所以,根据"根与根之差的绝对值 >= 1 “,先对区间[-100,-99]、[-99,-98]…[99,100]进行枚举,确定这些区间内是否有解,然后对所有有解的区间使用二分法就可以了。

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cstdlib>
using namespace std;
float a, b, c, d;
int n;
float ans[4];

float Equation(float x) {
	return ((a * x + b) * x + c) * x + d;
}

void solve(float l,float r) {
	if(Equation(l) * Equation(r) > 0 && ((r-l) < 1 || n >= 2))
    //区间等于1以内没有解,返回;
    //或者区间长度大于一,并且已经得到两个解,则只剩下一个解,如果该区间两端函数值相乘大于0,则可以直接返回,减少不必要的时间浪费
		return;
	float mid = (l + r) / 2;
	
	if(Equation(mid) <= 1e-4 && Equation(mid) >= -1e-4) {
		ans[++n] = mid;
		return;
	}
	solve(l,mid),solve(mid,r);
}

int main() {
	cin >> a >> b >> c >> d;
	solve(-100,100);
	cout << fixed << setprecision(2) << ans[1] << ' ' << ans[2] << ' ' << ans[3] << endl; 
	return 0;
}  

长路漫漫,未来可期;

发布了59 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/hou_shiyu/article/details/98874999