一道NOIP上古时代的联赛题,题目描述(我翻译的精简版…):
存在方程 f(x)=ax^3+bsquare(x)+cx+d=0, 已知有三个实数根在范围-100与100之内,解与解的差至少为1,请你求出这三个实数解,精确到小数点后2位。
先给出洛谷很多同学的标准解法:因为解与解的差至少为1,那么我们应该对于-100到100内所有为1的区间进行二分答案,直到我们找到三个解为止。
我的做法:对于-100 到 100这个区间进行切片,枚举切片的位置,那么必然存在三个区间包含了三个答案,对这三个区间进行二分,直到找到三个答案为止。
感觉自己这个做法很冒险,不清楚是否正确性充分,但是还是给出参考代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
double a, b, c, d;
double ans[505];
int cnt;
double pow(double x, int ex)
{
int i;
double ret=1;
for(i=1;i<=ex;i++)
{
ret*=x;
}
return ret;
}
double func(double x)
{
return a*pow(x,3)+b*pow(x,2)+c*x+d;
}
double bsearch(double left,double right)
{
if(func(left)*func(right)>0)
return 99999;
if(func(left)==0&&func(right)!=0)
{
return left;
}
if(func(right)==0&&func(left)!=0)
{
return right;
}
if(func(right)==0&&func(left)==0)
{
return left;
}
if(left>right-0.001)
{
return (left+right)/2;
}
double mid = (left+right)/2;
return min(bsearch(left,mid),bsearch(mid,right));
}
int main()
{
int i, j, k;
cin>>a>>b>>c>>d;
double y1, y2, y3;
/* for(i=1;i<=3;i++)
{
if(i==1)
{
y1=bsearch(-100,100);
}
if(i==2)
{
y2=bsearch(y1+1,100);
}
if(i==3)
{
y3=bsearch(y2+1,100);
}
}
cout<<y1<<' '<<y2<<' '<<y3<<endl;*/
for(i=-99;i<=99;i++)
{
for(j=i+1;j<=100;j++)
{
double y1 = bsearch(-100,i);
double y2 = bsearch(y1+1,j);
double y3 = bsearch(y2+1,100);
if(y1!=99999&&y2!=99999&&y3!=99999)
{
printf("%.2lf %.2lf %.2lf",y1,y2,y3);
return 0;
}
}
}
}

该博客讨论了NOIP的一道联赛题,涉及一元三次方程f(x)=ax^3+bx^2+cx+d=0的解法。题目要求找到在-100到100范围内差至少为1的三个实数根。文章对比了两种解题策略:一是采用二分法针对每个相隔1的区间搜索,二是通过切片枚举并二分查找。作者对自己的方法持保留态度,虽给出了代码,但不确定其正确性。
717

被折叠的 条评论
为什么被折叠?



