猫史档案馆


C++分治-一元三次方程-那里错了?

用户:happy_chickenhappy_chicken查看:6 回复:5 评论:6 创建时间:2023-12-05T18:58:42


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

输入 一行,包含四个实数a,b,c,d,相邻两个数之间用单个空格隔开。 输出 一行,包含三个实数,为该方程的三个实根,按从小到大顺序排列,相邻两个数之间用单个空格隔开,精确到小数点后2位。 样例输入  复制
1.0 -5.0 -4.0 20.0
样例输出  复制
-2.00 2.00 5.00
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
    double a,b,c,d;
    int num_of_times=0;
    cin>>a>>b>>c>>d;
    for(double x=-100;x<=100;x++){//ax^3+bx^2+cx+d
        if(num_of_times>=3)
            break;
        if((a*x*x*x+b*x*x+c*x+d)==0){
                printf("%.2f ",x);
                num_of_times++;
        }
        if((a*x*x*x+b*x*x+c*x+d)*(a*(x+1)*(x+1)*(x+1)+b*(x+1)*(x+1)+c*(x+1)+d)<0){
            double mid,left=x,right=x+1;
            bool flag=false;
            while(left-right>=0.0001){
                mid=(left+right)/2;
                if((a*mid*mid*mid+b*mid*mid+c*mid+d)>0)
                    right=mid;
                else if((a*mid*mid*mid+b*mid*mid+c*mid+d)<0)
                    left=mid;
            }
            printf("%.2f ",left);
            num_of_times++;
        }
    }
    return 0;
} 
/**************************************************************
    Problem: 1237
    User: zhaoweizhuo666 [zhaoweizhuo666]
    Language: C++
    Result: 答案错误
****************************************************************/

思想:
就是个求三个实根,不很简单,套个数学公式,可是:
center_image
写喜人!感觉枚举太土,于是使用二分:
center_image
画了个很好看的图,然后就做了
done。。。


回复

上一页1 页 / 共 1下一页
happy_chickenhappy_chicken

主要是找区间卡0,精度不高,找到后2分

点赞0


评论


PlumStevenPlumSteven

这东西盛金公式

点赞0


评论


PlumStevenPlumSteven

二分的话....大概不行吧

二分适用于解决的问题要求一定是线性的,三分得满足单峰性,你看你这图像就知道了

点赞0


评论


PlumStevenPlumSteven

附我当时写的代码(老早之前了),这码风大概是我去年的。

//盛金公式,自己写的(真的)

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
	double a, b, c, d;
	cin >> a >> b >> c >>d;
	//先算出A,B,C
	/*
	A=b2-3ac
	B=bc-9ad
	C=c2-3bd
	*/
	double A = 1.0*pow(b, 2)-3*a*c;
	double B = 1.0*b*c-9*a*d;
	double C = 1.0*pow(c, 2)-3*b*d;
	//判别式Δ=B2-4AC
	double Delta=1.0*pow(B, 2)-4*A*C;
	//题目明确表示,方程有三个不相等的实根,则使用盛金公式4
	//即Δ<0的情况
	//X1=(-b-2√A cos(θ/3))/3a
	//X2=(-b+√A(cos(θ/3)+√3 sin(θ/3)))/3a
	//X3=(-b+√A(cos(θ/3)-√3 sin(θ/3)))/3a
	//其中θ=arccos T
	//T=(2Ab-3aB)/(2*√A3)
	double T = (2*A*b-3*a*B)/(2*sqrt(pow(A,3)));
	double theta = acos(T);
	//为了从小到大排列,采用数组
	double x[3];
	x[0] = (-b-2*sqrt(A)*cos(theta/3))/3*a;
	x[1] = (-b+sqrt(A)*(cos(theta/3)+sqrt(3)*sin(theta/3)))/3*a;
	x[2] = (-b+sqrt(A)*(cos(theta/3)-sqrt(3)*sin(theta/3)))/3*a;
	//排序
	sort(x, x+3);
	printf("%.2lf %.2lf %.2lf", x[0], x[1], x[2]);
	return 0;
}

洛谷上可以过

点赞0


评论


tiger666250tiger666250

还有一种方法就是用数学计算出三次函数的两个极值(好像求导可以解决我忘了)然后三段二分(

 

 

点赞0


评论