Problem 2220 : The Number of the Real Roots of a Cubic Equation

解法

f(x)=ax^3+bx^2+cx+dとして、f(x)のグラフを考える。
f'(x)を考えるとグラフの増減表が書ける。
増減表が書ければ単調な区間がわかるため、それぞれについて二分法を用いれば実数解がわかる。


単調な区間の数は3個または1個(-∞,∞)なので、それぞれの場合について場合わけして二分法を用いる。

ソースコード

int p,m;
double a,b,c;

double f(double x)
{
	return x*x*x+a*x*x+b*x+c;
}
double solve(double lo,double hi,bool dec)
{
	if(hi-lo<EPS)return lo;
	double mid=(lo+hi)/2;
	return (f(mid)<0)^dec?solve(mid,hi,dec):solve(lo,mid,dec);
}

int main()
{
	int n,w,x,y,z; scanf("%d",&n);
	rep(i,n)
	{
		scanf("%d%d%d%d",&w,&x,&y,&z);
		a=1.0*x/w; b=1.0*y/w; c=1.0*z/w;
		p=m=0;
		
		double d=a*a-3*b;
		if(d<0)
		{
			double x=solve(-INF,INF,0);
			if(x<-EPS)m++; else if(x>EPS)p++;
		}
		else
		{
			double p1=(-a-sqrt(d))/3,p2=(-a+sqrt(d))/3;
			double x1=solve(-INF,p1,0),x2=solve(p1,p2,1),x3=solve(p2,INF,0);
			
			if(f(-INF)*f(p1)<=0)
			{
				if(x1<-EPS)m++; else if(x1>EPS)p++;
			}
			if(f(p1)*f(p2)<=0)
			{
				if(x2<-EPS)m++; else if(x2>EPS)p++;
			}
			if(f(p2)*f(INF)<=0)
			{
				if(x3<-EPS)m++; else if(x3>EPS)p++;
			}
		}
		printf("%d %d\n",p,m);
	}
	return 0;
}