算法訓練 一元三次方程求解

 題目鏈接                               藍橋杯 算法訓練---------題解

錦囊1

枚舉加二分答案。

錦囊2

先用枚舉初步確定三個根的範圍,比如f[i]*f[i+1]<0則可知道[i,i+1]之間有一個根,然後再對於每個範圍內二分求根。

問題描述

  有形如:ax3+bx2+cx+d=0 這樣的一個一元三次方程。給出該方程中各項的係數(a,b,c,d 均爲實數),並約定該方程存在三個不同實根(根的範圍在-100至100之間),且根與根之差的絕對值>=1。要求三個實根。。

輸入格式

  四個實數:a,b,c,d

輸出格式

  由小到大依次在同一行輸出這三個實根(根與根之間留有空格),並精確到小數點後2位

方法一:直接枚舉。

#include <cstdio>
#include <cmath>

int main(int argc, char** argv) {
	double a, b, c, d;
	scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
	double left = -100;
	int cnt = 0;
	for(double x = -100; cnt< 3 && x < 100; x += 0.01){
		if( fabs(a*x*x*x + b*x*x + c*x + d) < 1e-5 ){
			cnt++;
			printf("%.2lf ",x);		
		}
	}
	return 0;
}

方法二:枚舉區間,看解存在於哪個區間裏,逐漸縮小區間範圍,確定解。

#include <cstdio>
#include <cmath>
double a, b, c, d;
double f(double x){
	return a*x*x*x + b*x*x + c*x + d;
}

int main(int argc, char** argv) {	
	scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
	for(double i = -100; i < 100; i++){
		double left = i, right = i+1;
		if(fabs(f(left)) <= 1e-16){ //當左邊界已經是答案,防止重複得到兩次 
			printf("%.2lf ",left);
		}else if(f(left) * f(right) < 0){ 			
			while( right - left >= 1e-5){
				double mid = (left+right)/2;
				if(f(left) * f(mid) <= 0)  right = mid;
				else  left = mid;
			}
			printf("%.2lf ",left);
		}
	}
	return 0;
}

 

樣例輸入

1 -5 -4 20

樣例輸出

-2.00 2.00 5.00

數據規模和約定

  |a|,|b|,|c|,|d|<=10

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