zoj3658 Simple Function (函数值域)

Simple Function


Time Limit: 2 Seconds       Memory Limit: 32768 KB

Knowing that x can be any real number that x2 + Dx + E ≠ 0. Now, given the following function

y = f(x) =
Ax2 + Bx+ C
-------------------
x2 + Dx + E

What is the range of y.

Input

The first line contains a single integer T (T ≤ 10000), indicating that there are T cases below.

Each case contains five integers in a single line which are values of ABCD and E (-100 ≤ ABCDE ≤ 100).

Output

For each case, output the range of y in the form of standard interval expression like in a single line.

The expression is made up by one interval or union of several disjoint intervals.

Each interval is one of the following four forms: "(a, b)", "(a, b]", "[a, b)", "[a, b]"(there is a single space between ',' and 'b'), where ab are real numbers rounded to 4 decimal places, or "-INF" or "INF" if the value is negative infinity or positive infinity.

If the expression is made up by several disjoint intervals, put the letter 'U' between adjacent intervals. There should be a single space between 'U' and nearby intervals.

In order to make the expression unique, the expression should contain as minimum of intervals as possible and intervals should be listed in increasing order.

See sample output for more detail.

Sample Input

5
1 1 1 2 3
0 1 0 1 -10
-3 -1 0 -1 -1
0 0 0 0 0
1 3 0 2 0

Sample Output

[0.3170, 1.1830]
(-INF, INF)
(-INF, -1.8944] U [-0.1056, INF)
[0.0000, 0.0000]
(-INF, 1.0000) U (1.0000, 1.5000) U (1.5000, INF)
关于求值域,在高中学了很多方法,在这里我不推荐通过移项再根据x来算Δ>=0的方法来求y的值域,我之前就是这样写的,因为这样算出来的Δ值可能有很多种,而且意义不明确(如果数学功底不够就看不出来),太过麻烦,最后讨论分母为0去断点时也很麻烦
下面讲解时修改别人的,因为他的跟我的有点出入。

题目大意:

描述起来很简单,求f(x) = (Ax^2 + Bx + C) / (x^2 + Dx + E)的值域。

解题思路:

分子分母都含有自变量x,不好处理。最简单的想法就是把分子上的自变量消去。(二次->一次->零次)。然后就是各种情况讨论。

1.二次->一次

f(x) =  (Ax^2 + Bx + C) / (x^2 + Dx + E)

=  A + (bx + c) / (x^2 + Dx + E) (其中b=B-A*D, c=C-A*E)

=  A + g(x)

这样我们把分子的二次项消除了。注意之后的结果区间都要加上A。

2.一次-> 零次

(1) 若B = 0。那么g(x) = c / (x^2 + Dx + E)

(a)如果c=0。则值域为[0, 0].

(b)如果c!=0。则此时分母的式子是一个开口向上的抛物线,设其极小值为mins,则取值区间为[mins, INF).

此时需要对mins和c的正负情况讨论才能写出正确区间。(mins的正负即表示Δ)

c>0时

    • mins>0  值域为 (0, c/mins].
    • mins>0  值域为 (0, INF].
    • mins<0  值域为 (-INF, c/mins] U (0, INF)

c<0时同上分析,区间颠倒下就可以了。

(2) 若b != 0。那么g(x) = (bx + c) / (x^2 + Dx + E)

要消去一次项,我们可以换元,令t=b*x + c得到

g(t) = b*b*t / (t^2 + bb*t + cc)   其中bb=D*b-2*c,cc=(c*c+E*b*b-D*b*c);

(1)如果t取0,则g(t)=0;

(2)当t!=0时 g(x) =b*b/(t+cc/t + bb) = h(t)

此时要求h(t)= b*b/(t+cc/t + bb)的值域(t!=0)。只有分母有自变量,非常好求解了。注意最后要把0点补回去。

(i) cc<0 时。t+cc/t 能取遍(-INF, INF)。所以值域的为(-INF, INF)。

(ii) cc>0 时。t+cc/t 的值域为(-INF, 2√cc] U [2√cc, INF)

故分母的值域为(-INF, 2√cc+bb] U [2√cc+bb, INF)

全部的值域易得。我这里不需要讨论分子分母的正负号,但是需要确定区间的范围,细心点就好了,详见代码吧。

#include<stdio.h>
#include<math.h> int main()
{
int T;
double A,B,C,D,E,a,b,c,bb,cc,x1,x2,temp1,temp2,y1,mins;
scanf("%d",&T);
while(T--)
{
scanf("%lf%lf%lf%lf%lf",&A,&B,&C,&D,&E);
a=A;
b=B-A*D;
c=C-A*E;
mins=E-D*D/4;//分母抛物线的极大值
if(b==0)//f(x)=A+((B-A*D)*x+C-A*E)/(x*x+D*x+E),f(x)=a+(b*x+c)/(x*x+D*x+E)
{
if(c==0)
printf("[%.4f, %.4f]\n",A,A);
else if(c>0)
{
if(mins>0)
printf("(%.4f, %.4f]\n",A,c/mins+A);
else if(mins<0)
printf("(-INF, %.4f] U (%.4f, INF)\n",c/mins+A,A);
else printf("(%.4f, INF)\n",A);
}
else
{
if(mins>0)
printf("[%.4f, %.4f)\n",c/mins+A,A);
else if(mins<0)
printf("(-INF, %.4f) U [%.4f, INF)\n",A,c/mins+A);
else printf("(-INF, %.4f)\n",A);
}
}
else //b!=0情况,f(x)=A+b*b/(t+(c*c+E*b*b-D*b*c)/t+D*b-2*c)
{
x1=-c/b;
if(x1*x1+D*x1+E==0)//排除那种分子分母有公因式的情况
{
x2=-D-x1;
if(x1==x2)
printf("(-INF, %.4f) U (%.4f, INF)\n",A,A);
else
{//(b*(x-x1))/((x-x1)*(x-x2))
y1=b/(x1-x2);
if(y1>0)
printf("(-INF, %.4f) U (%.4f, %.4f) U (%.4f, INF)\n",A,A,A+y1,A+y1);
else
printf("(-INF, %.4f) U (%.4f, %.4f) U (%.4f, INF)\n",A+y1,A+y1,A,A);
}
}
else
{
bb=D*b-2*c;
cc=(c*c+E*b*b-D*b*c);
if(cc>0)//分母化成了g(t)=t+cc/t+bb,t=b*x+c,分子变成了b*b,所以不用考虑分子的符号了
{
temp1=2.0*sqrt(cc);
temp2=temp1+bb;//这便是分母的极大值
temp1=-temp1+bb;//分母的极小值
if(temp1>0)//极小值大于0
printf("(-INF, %.4f] U [%.4f, INF)\n",A+b*b/temp2,A+b*b/temp1);
else if(temp1==0)//极小值为0
printf("(-INF, %.4f]\n",A+b*b/temp2);
else if(temp2<0)//极大值小于0
printf("(-INF, %.4f] U [%.4f, INF)\n",A+b*b/temp2,A+b*b/temp1);
else if(temp2==0)//极大值为0
printf("[%.4f, INF)\n",A+b*b/temp1);
else printf("[%.4f, %.4f]\n",A+b*b/temp1,A+b*b/temp2);
}
else if(cc<0)
printf("(-INF, INF)\n");
else
printf("(-INF, INF)\n");
}
}
}
return 0;
}
上一篇:从Oracle迁移到Mysql之前必须知道的50件事


下一篇:HTML5: Screen Orientation API