uvaoj10341(详解 + 一直WA的,快来看看)

uvaoj10341

                                  

Solve the equation:
p ∗ e −x + q ∗ sin(x) + r ∗ cos(x) + s ∗ tan(x) + t ∗ x 2 + u = 0
where 0 ≤ x ≤ 1.
Input
Input consists of multiple test cases and terminated by an EOF. Each test case consists of 6 integers in
a single line: p, q, r, s, t and u (where 0 ≤ p, r ≤ 20 and −20 ≤ q,s,t ≤ 0). There will be maximum
2100 lines in the input file.
Output
For each set of input, there should be a line containing the value of x, correct up to 4 decimal places,
or the string ‘No solution’, whichever is applicable.
Sample Input
0 0 0 0 -2 1
1 0 0 0 -1 2
1 -1 1 -1 -1 1
Sample Output
0.7071
No solution
0.7554




------------------------------------------------------------------------------------------------

这个题,让我非常的无奈!精确度一定要把握好!!!!!

题目分析:

这个题一看输出有小数点,就大概知道考点了,几乎就是猜数了,就是二分法来带入使之符合  方程的解 。方程值大了,小了,那么二分法取值做出相应的改变。


那么,重要的就是这个方程了,这个方程的关键信息来源于p,q,r,u,s的正负,题目已经明确给出了!!

    p ∗ e (−x) + q ∗ sin(x) + r ∗ cos(x) + s ∗ tan(x) + t ∗ x *x

    x越大,p ∗ e (−x)越小,r ∗ cos(x)越小,而且都>0。 q ∗ sin(x) , s ∗ tan(x) ,t ∗ x *x越大,且都<0.

     正(减函数) + 负(增函数)-〉所以函数整体是一个减函数



     x越大,函数值越小。这样确定了二分法的 取值变化。

    

------------------------------------------------------------------------------------------------


易错点1:

    若程序总是WA。你们先带这两组数据看看

    0 0 0 0 0 1

    0 0 0 0 0 -1

   输出应该都是 No solution 。

    这是边界极限,x不管无限趋近0(或 1) ,函数值仍然大于0(或小于0)的情况,试一下。

     就这两种极限,所以可以这样卡条件:

     先判断

     if(check(0)>0 ||  check(1)<0)

     {

           printf("No solution\n");

           continue;

     }

     也可以这样,最后去判断

      if(fabs(check(mid)-0.0)<1e-6)
         printf("%.4f\n",mid);
 else
 printf("No solution\n");



易错点2:

   谁用的是high-low>1e-6做的循环条件,就会wrong answer! 不精确 !本以为输出结果是小数点后四位,就确定到1e-6即可了,带了N次一直WA ,快撞墙了 ,但是忘了high 与 low 应无限接近相减几乎为0 1e-8

较精确,一改便通过了

   

		while(high-low>1e-8)
		{
			mid = (high + low)/2;
			if(check(mid) > 0 )low  = mid;
			else high = mid ;			
	
		}
       

    或者直接让它循环100次,绝对精确!

   

		low = 0; high = 1;
		for(i=0;i<100;i++)
		{
			mid = (low+high)/2;
			if(check(mid)>0)low = mid;
			else high =mid;
		}

-------------------------------------------------------------------------------------------------------------------


接下来就是整体代码了  ,放了两种。

这种RUN Time 0.006!

#include<stdio.h>
#include<math.h>
int p,q,r,s,t,u;
double check(double x)
{

	return p*exp(x*-1)+q*sin(x)+r*cos(x)+s*tan(x)+t*x*x + u ;
		
}

int main()
{
	double mid , low = 0,high = 1;
	
	while(scanf("%d %d %d %d %d %d",&p,&q,&r,&s,&t,&u)!=EOF)
	{	
	
		low = 0;high = 1;
		while(high-low>1e-8)
		{
			mid = (high + low)/2;
			if(check(mid) > 0 )low  = mid;
			else high = mid ;			
	
		}
		
	   if(fabs(check(mid)-0.0)<1e-6)
		printf("%.4f\n",mid);
		else
		printf("No solution\n");
	
	}

	return 0;
}
这种Run Time 0.026

#include<stdio.h>
#include<math.h>
int p,q,r,s,t,u;

double  check(double x)
{

	return  p*exp(x*-1)+q*sin(x)+r*cos(x)+s*tan(x)+t*x*x+u;
	
	
}

int main()
{
	double low,mid,high;
	int i;
	while(scanf("%d %d %d %d %d %d",&p,&q,&r,&s,&t,&u)!=EOF)
	{
		low = 0; high = 1;
		for(i=0;i<100;i++)
		{
			mid = (low+high)/2;
			if(check(mid)>0)low = mid;
			else high =mid;
		}

		if(fabs(check(mid)-0.0)<1e-6)
		printf("%.4f\n",mid);
		else
		printf("No solution\n");
	}

	return 0;
}



你可能感兴趣的:(c,二分法acm)