• ACM Steps_Chapter Four_Section1


    Can you solve this equation?

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    double comp(double x)
    {
    	return ( 8*pow(x,4) + 7*pow(x,3) + 2*pow(x,2) + 3*x + 6 );
    }
    int main()
    {
    	int t;
     	double Y;
     	scanf("%d",&t);
     	while( t-- && scanf("%lf",&Y) )
     	{
      		if( comp(0.0) > Y || comp(100.0) < Y)
      	{
       	printf("No solution!\n");
       	continue;
      	}
      	double l = 0.0, r = 100.0 ;
      	while( r - l > 1e-6)
      	{
       		double mid = ( l + r ) / 2.0;
       		double ret = comp( mid );
       		if( ret < Y)
        		l = mid + 1e-6;
       		else
        		r = mid - 1e-6;
      	}
      	printf("%.4lf\n", (l + r) / 2.0);
     	}
     	return 0;
    }
    

    Strange fuction

    /*
    求函数的最小值,首先求导的导函数为:G(x) = 42 * x^6+48*x^5+21*x^2+10*x-y (0 <= x <=100)
    分析导函数的,导函数为一个单调递增的函数。如果导函数的最大值小于0,
    那么原函数在区间内单调递减。
    即F(100)最小;如果但函数的最小值大于0,那么原函数在区间内单调递增,即F(0)最小。
    如果导函数既有正又有负
    又由于导函数是单增函数,所以必有先负后正,即原函数必有先减后增的性质。
    求出导函数的零点就是原函数的最小值点。
    求导函数最小值方法是2分法.
    */
    #include<iostream>
    #include <cstdio>
    #include <cmath>
    double Y;
    double cpt( double x )      //导函数
    {
    	return ( 42 * pow(x,6) + 48 * pow(x,5) + 21*pow(x,2) + 10*x );
    }
    double ret( double x )     //求结果
    {
    	return ( 6 * pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-Y*x );
    }
    int main()
    {
    	int t;
     	double s;
     	scanf ("%d",&t);
     	while( t-- && scanf("%lf",&Y) )
     	{
      		double l = 0.0, r = 100.0,mid;
      		while( r - l > 1e-8 )
      		{
       			mid = ( l + r ) / 2.0;
       			s = cpt( mid );
       			if ( s > Y )
        			r = mid - 1e-8;
       			else
        			l = mid + 1e-8;
      		}
      		mid = ( l + r ) / 2.0;
      		printf("%.4lf\n", ret(mid) );
     	}
     	return 0;
    }
    

    Pie

    /*
    题目大意是要办生日Party,有n个馅饼,有f个朋友,接下来是n个馅饼的半径。然后是分馅饼了,
    注意咯自己也要,大家都要一样大,形状没什么要求,但都要是一整块的那种,
    也就是说不能从两个饼中各割一小块来凑一块,像面积为10的和6的两块饼
    (饼的厚度是1,所以面积和体积相等),
    如果每人分到面积为5,则10分两块,6切成5,够分3个人,如果每人6,则只能分两个了!
    题目要求我们分到的饼尽可能的大!
    
    只要注意精度问题就可以了,一般WA 都是精度问题
    运用2分搜索:
    首先用总饼的体积除以总人数,得到每个人最大可以得到的V,
    但是每个人手中不能有两片或多片拼成的一块饼,
    最多只能有一片分割过得饼。用2分搜索时,把0设为left,把V 设为right。mid=(left+right)/2;
    搜索条件是:以mid为标志,如果每块饼都可以分割出一个mid,那么返回true,
    说明每个人可以得到的饼的体积可以
    大于等于mid;如果不能分出这么多的mid,那么返回false,
    说明每个人可以得到饼的体积小于等于mid。
    (1)精度为:0.000001
    (2)   pi 用反余弦求出,精度更高。
    */
    #include <iostream>
     #include <stdio.h>
     #include <math.h>
     using namespace std;
     double pi = acos(-1.0);
     int F,N;
     double V[10001];
     bool test(double x)
     {
         int num=0;
         for(int i = 0; i < N;i++)
         {
             num += int(V[i]/x);
         }
         if(num>=F)
         return true;
         else return false;
     }
     int main()
     {
         int t,r;
         double v,max,left,right,mid;
         scanf("%d",&t);
         while(t--)
         {
             scanf("%d%d",&N,&F);
             F = F+1;
             for(int i = 0; i < N; i++)
             {
                 scanf("%d",&r);
                 V[i] = pi*r*r;
                 v += V[i];
             }
             max = v/F;
             left = 0.0;
             right = max;
             while((right-left)>1e-6)//注意这里的精度问题。
             {
                 mid = (left+right)/2;
                 if(test(mid))
                 left = mid;
                 else right = mid;
             }
             printf("%.4f\n",mid);
         }
         return 0;
     }
    

    Can you find it?

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int L, N, M, s, x, flag, k;
    int a[501], b[501], c[501], sum[250001];
    int Judge(int p)
    {
    	int l, r, m;
    	l=0;
       	r=k-1;
    	if(sum[l]==p||sum[r]==p) 
    	{   
    		flag=1;
    		return 1;
    	}
    	while(l<=r)
    	{
       		m=(l+r)/2;
       		if(sum[m]==p)
    		{   
    			flag=1; 
    			return 1; 
    		}
       		else if(sum[m]>p) 
    		   r=m-1;
       		else if(sum[m]<p) 
    		   l=m+1;
    	}
    	return 0;
    }
    int main()
    {
    	int i, j, t=0;
    	while(cin>>L>>N>>M)
    	{
       		printf("Case %d:\n", ++t);
       		for(i=0;i<L;i++)
        		scanf("%d",&a[i]);
       		for(i=0;i<N;i++)
        		scanf("%d",&b[i]);
       		for(i=0, k=0;i<L;i++)
       		{
        		for(j=0;j<N;j++)
         			sum[k++]=a[i]+b[j];
       		}
    		sort(sum,sum+k);
       		for(i=0;i<M;i++)
        		scanf("%d",&c[i]);
       		cin>>s;
       		while(s--)
       		{
        		cin>>x;
         		flag=0;
        		for(i=0;i<M;i++)
       			{ 
         			if(x-c[i]>sum[k-1]) 
    				 	continue;
         			if(Judge(x-c[i]))   
    				 	break;
    			}
        		if(flag) 
    				printf("YES\n");
        		else 
    				printf("NO\n");
       		}
    	}
    	return 0;
    }
    

    Toxophily

    /*
    用公式,根据正交分解坐标系,得出方程的通式。
    想 x^2*g/(2*v^2)*tan^2(?) - x*tan(?) +y + x^2*g/(2*v^2) = 0;
     即:a = g*pow(x,2)/(2*pow(v,2));
        b = -x;
        c = y + g*pow(x,2)/(2*pow(v,2));
    根据求根公式求出根。
    注意讨论:
    (1) x==0&&y==0时,? = 0;
    (2) x==0&&y>0时,?=90;
    (3) 方程无解时 ?=-1;
    (4) 方程的解为负数时,?=-1;(0<=?<=90)。
    */
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    using namespace std;
    int main()
    {
        int t;
        double a,b,c,angle,z;
        double x,y,v,g = 9.8,T,ans1,ans2;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lf%lf%lf",&x,&y,&v);
            if(x==0&&y==0)
            printf("0\n");
            else if(x==0&&y>0)
            printf("90\n");
            else
            {
                a = g*pow(x,2)/(2*pow(v,2));
                b = -x;
                c = y+a;
                T = pow(b,2) - 4*a*c;
                angle = 0;
                if(T<0)
                printf("-1\n");
                else
                {
                    ans1 = ((-b)+pow(T,1.0/2))/(2*a);
                    ans2 = ((-b)-pow(T,1.0/2))/(2*a);
                    if(ans1>=0) angle = atan(ans1);
                    if(ans2>=0)
                    {
                        z =  atan(ans2);
                        if(z<angle) angle = z;
                        printf("%.6f\n",angle);
                    }
                    if(ans1<0&&ans2<0)
                        printf("-1\n");
                }
            }
        }
        return 0;
    }
    

    Turn the corner

    /*
    思路:显然为了让车子能顺利通过弯道,我们应该使车子擦着左边那个墙角走,
    在转弯的过程中,车子的右下端(点p)露在最外面,所以我们只需判断点p能否顺利通过就行。
    下面就是数学知识了,我们可以建立p的横坐标关于θ的函数,这个画个图可以算出来,
    现在给出其函数表达式:f(θ)=l*cos(θ)-(x*cos(θ)-d)/sin(θ).
    f(θ)在区间(0,π/2)上先增后减,所以我们需要求出f(θ)的最大值,
    若f(θ)<=y则车子可以通过,否则不能通过。
    
    对于这样的一个先增后减的函数,我们可以用三分求出其极大值。
    */
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    
    using namespace std;
    const double PI=acos(-1.0);
    const double eps=1.0e-6;
    double x,y,l,d;
    
    double f(double t)//计算右下方顶点的横坐标(离第一条竖直线的距离)
    {
        return l*cos(t)-(x*cos(t)-d)/sin(t);
    }
    
    int main()
    {
        double low,up,mid1,mid2;
        while(cin>>x>>y>>l>>d)
        {
            low=0;
            up=PI/2;
            while(up-low>=eps)
            {
                mid1=low+(up-low)/3;
                mid2=up-(up-low)/3;
                if(f(mid1)<=f(mid2))
                    low=mid1;
                else
                    up=mid2;
            }
            if(f(mid1)<=y)
                printf("yes\n");
            else
                printf("no\n");
        }
        return 0;
    }
    

    Cable master

    #include<iostream>
    #include<iomanip>
    using namespace std;
    double a[10005];
    int N,K;
    int check(double x)
    {
        int i,sum=0;
        for(i=0;i<N;i++)
            sum+=(int)(a[i]/x);
        if(sum<K)  
    		return 0;
        return 1;
    }
    int main()
    {
        int i;
        double left,right,mid,max;
        while(scanf("%d%d",&N,&K)!=EOF)
        {
            if(N==0&&K==0) break;
            max=0;
            for(i=0;i<N;i++)
            {
                scanf("%lf",&a[i]);
                if(a[i]>max)
                    max=a[i];
            }
            left=0;
    		right=max;
            while(right-left>0.001)
            {
                mid=(right+left)/2;
                if(check(mid))  
    				left=mid;
                else 
    				right=mid;
            }
            printf("%.2lf\n",mid);
        }
        return 0;
    }
    

    Dome of Circus

    /*
    这个题虽然是三维的,但是可以很容易的转化到二维去
    。来看X-Z这个平面,我们将所有的点进行圆周映射,然后将所有的点都投影到
    X-Z平面的的第一象限去,然后问题就转化成了在X-Z平面上找到一条斜率为负
    的直线L,L和X正方向、Z正方向围成的三角形包含所有点,如果假设L和X轴的
    交点为R,和Z轴焦点为H,要求pi*H*R^2的值最小。
       L这条线必定和某一
    个给定的点擦边,也就是经过那个点,我们假设它经过P(a, b), 并且L的斜率
    为K(K < 0),那么L的方程就可以表示为 L:  y = K * (x - a) + b,则H和R就
    可以利用这个方程表示出来:
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #define eps 1e-7
    #include <set>
    #include <vector>
    using namespace std;
    struct point{
        double x,y,z;
        point(){}
        point(double a, double b, double c){x = a, y = b, z = c;}
    }p[11111];
    int n,T;
    double a,b,c;
    double cal(double r){
        double h ,Max = 0;
        for(int i = 0; i < n; i ++){
            h = p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y));
            Max = max(h,Max);
        }
        return r * r * Max;
    }
    void thi(double &r, double &h){
        double low = 0.0, high = 10000;
        double m1,m2;
        while(low + eps < high){
            m1 = (low + high) / 2.0;
            m2 = (m1 + high) / 2.0;
            if(cal(m1) <= cal(m2)) high = m2;
            else {
                low = m1;
            }
        }
        r = low;
        h = -1;
        for(int i = 0; i < n; i ++){
            h = max(h,p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y)) );
        }
    }
    int main(){
        scanf("%d",&T);
        while(T --){
            scanf("%d",&n);
            for(int i = 0; i < n; i ++){
                scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
            }
            double r,h;
            thi(r,h);
            printf("%.3f %.3f\n",h,r);
        }
    	return 0;
    }
    


  • 相关阅读:
    Python批量爬取唯美类图片
    查找Windows启动程序
    在Windows10中进行蓝屏排查
    在Windows 10中应该记住的完整的多指触摸板手势
    通过命令行工具远程注销用户
    Windows 7,8.1和10中的隐藏退出资源管理器选项
    找出正在使用的全局热键
    windows10中创建环境变量
    mysql高级(锁机制)
    mysql高级(查询截取分析)
  • 原文地址:https://www.cnblogs.com/oldoldb/p/3311319.html
Copyright © 2020-2023  润新知