1. 程式人生 > >luogu1024 一元三次方程求解

luogu1024 一元三次方程求解

iostream ble tar names 註意 stream 左右 ret ==

題目大意

已知一元三次方程\(ax^3+bx^2+cx+d=0\)

  1. 有且只有3個根
  2. \(\forall x, x\in[-100,100]\)
  3. \(\forall x_1,x_2,|x_1-x_2|\geq1\)
  4. 定理:令\(f(x)=ax^3+bx^2+cx+d\),則\(f(l)f(r)<0\Leftrightarrow \exists x\in [l,r],使得f(x)=0\)

思路

本題中的條件3的表達形式太討厭了,我們求點利用的是區間,想要的是區間的性質,這才有助於我們求點。怎麽翻譯3呢?性質3中的那個“1”指的是區間的長度。所以翻譯為:對\(\forall p\),方程的根落在區間\([p,p+1]\)

的個數不多於1。若個數等於1,則\(p,p+1\)性質4中的\(l,r\)的性質。
從拿到題開始我們很容易想到二分。二分求點,我們要的是點右方區間具有某一特定性質,點左方區間具有另一特定性質。這個“特殊性質”便是:一方有解,另一方無解。因此我們對於每個滿足性質4的長度為1的區間二分即可。

註意

  • 上文中的“特殊性質”不可以是“左側圖象在x軸一側,右側圖像在x軸另一側”,因為該區間上的圖象不一定具有單調性,所以我們無法判斷左右側圖象分別具體在x軸的上側還是下側。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const double EPS = 0.0001; double A, B, C, D; double Bsearch(double l, double r, double k, double eps, double (*GetVal)(double, double)) { double mid; //printf("l %.2f r %.2f\n", l, r); while(r - l > eps) { //printf("l %.2f r %.2f\n", l, r);
mid=(l+r)/2.000; if(GetVal(l, mid) < k) r = mid; else l = mid; } return mid; } double Func(double x) { return A * x * x * x + B * x * x + C * x + D; } double GetVal(double l, double r) { return Func(l) * Func(r); } int main() { cin>>A>>B>>C>>D; int ansCnt = 0; double ans[4]; for(double l = -100; l <= 99; l += 1) { double r = l + 1; //printf("l %.2f r %.2f\n", l, r); if(Func(l) == 0) ans[++ansCnt] = l; else if(Func(l) * Func(r) < 0) { //printf("ok\n"); ans[++ansCnt] = Bsearch(l, r, 0, EPS, GetVal); } } //printf("%.2f %.2f %.2f\n", ans[1], ans[2], ans[3]); //sort(ans+1, ans + 3 + 1); for(int i=1; i<=ansCnt; i++) printf("%.2f ", ans[i]); return 0; }

luogu1024 一元三次方程求解