• codeforces #198 div.2 解题报告


    A 题 签到题。不过我挺水的中途被hack成功了。。。后来一直在测数据。

    这题用gcd求出lcm。然后根据公式就可以直接计算获得

    #include<stdio.h>
    int Gcd(int a,int b)
    {
        if(b>0)
        {
            a=a%b;
            return Gcd(b,a);
        }
        else return a;
    }
    int main()
    {
        int x,y,a,b,i,j,c,k;
        while(scanf("%d %d %d %d",&x,&y,&a,&b)!=EOF)
        {
            c=0;
            if(x>y) k=Gcd(x,y);
            else k=Gcd(y,x);
            k=x*y/k;
            if(a%k) printf("%d
    ",b/k-a/k);
            else printf("%d
    ",b/k-a/k+1);
        }
    }


    B题,这道题目出题者明显出难了。作者也在事后给了道歉原话:I want to apologize for not estimating the real difficulty of this task. It turns out that it was more complicated than we thought it might be.

    我就是我这么机智的弱菜怎么不会。其实这个题目用到的知识我是见过的。但没想到。这里首先你必须知道任意多边形的面积公式。

    |x1 y1|	|x2 y2|	|x3 y3|	|x5 y5|	|x6 y6|	|x7 y7|	   |xn-1 yn-1|	|xn  yn |	
    |x2 y2|+|x3 y3|+|x4 y4|+|x6 y6|+|x7 y7|+|x8 y8|...+|xn   yn  |+ |x1  y1 |*0.5=S

    这里用到的知识点就是你要枚举平面内所有的直线,再根据直线枚举所有的点与这条直线构成的三角形的面积。

    网上的一般代码都是这个公式的简化,所以希望读者能过牢记这个万能的计算任意多边形(凹、凸)的公式。

    而这个叉积的面积当点为逆时针排列时S为负数,当点为正时针排列时S为正数。也就是说如果从与这条直线所构成的三角形中选两个组成四边形,那么这两个点必须分布在直线两侧,使得他们分别与直线构成的三角形通过公式计算出的值为一正一负。设直线为 ab那么枚举的点c与之组成的序列acb可能是正也可能是负数。我们要用贪婪的方式保留这两个最大子面积。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    typedef struct Point
    {
    	int x,y;
    }Point;
    Point p[305];
    double area(Point a,Point b,Point c)
    {
    	return a.x*b.y-b.x*a.y+b.x*c.y-c.x*b.y+c.x*a.y-a.x*c.y;    /*公式直接计算*/
    }
    double max(double s1,double s2)
    {
    	return s1>s2?s1:s2;
    }
    int main()
    {
    	int n;
    	while(scanf("%d",&n)!=EOF)
    	{
    		int i,j,k;
    		double s1,s2,s3,s;
    		for(i=0;i<n;i++) scanf("%d %d",&p[i].x,&p[i].y);
    		s3=0;
    		for(i=0;i<n;i++)
    		{
    			for(j=i+1;j<n;j++)
    			{
    			    s1=s2=0;
    				for(k=0;k<n;k++)
    				{
    					if(k!=i&&k!=j)
    					{
    						s=area(p[i],p[k],p[j]);
    						if(s>0) s1=max(s1,fabs(s)/2);
    						else if(s<0) s2=max(s2,fabs(s)/2);
    					}
    				}
    				if(s1!=0&&s2!=0)    s3=max(s1+s2,s3);    //子面积必须分布在直线两侧,若某个子面积为0.则说明所有点在这条直线的同一侧。见测试#23
    			}
    		}
    		printf("%.6lf
    ",s3);
    	}
        return 0;
    }
    
    
    
    
    

    C 题


    Consider 6 possible routes:

    • [2, 3, 5]: total distance traveled: |2 – 0| + |3 – 2| + |5 – 3| = 5;
    • [2, 5, 3]: |2 – 0| + |5 – 2| + |3 – 5| = 7;
    • [3, 2, 5]: |3 – 0| + |2 – 3| + |5 – 2| = 7;
    • [3, 5, 2]: |3 – 0| + |5 – 3| + |2 – 5| = 8;
    • [5, 2, 3]: |5 – 0| + |2 – 5| + |3 – 2| = 9;
    • [5, 3, 2]: |5 – 0| + |3 – 5| + |2 – 3| = 8.

    The average travel distance is = = .


    这周似乎都是数学题,这道题是组合问题。首先你要推一下公式。

    我们看到最终结果中分母是6。这个6就是A(3,3);

    而分子是不同元素相减的结果。可以发现除了0以外其他元素都是数组中的。

    可以将分子C分解成c1=|2-0|+|2-0|+|3-0|+|3-0|+.....+|5-0|+|5-0|;

    c2=|3-2|+|5-3|+.....|2-3|;

    可以发现每个组合会出现2次即A(2,2)次;

    那么推广一下c1=sum(a[n])*A(n-1,n-1);

    c2=C(2,n)*A(n-1,n-1)*sum(abs(a[i]-a[j]));

    c2+c1=A(n-1,n-1)*(sum(a[n])+2*sum(a[i]-a[j])); a[i]>a[j]

    与分母A(n,n)进行化简得;

    结果为(sum(a[n])+2*sum(a[i]-a[j]))/n; a[i]>a[j]

    可是要枚举所有的组合是会超时的,但根据先用冒泡排序,再根据c2的组成结构我们也能很好得发现规律。

    如例子中c2=2*((3-1)+(3-2)+(2-1));

    轻松得发现3出现了2次,2出现1次,-2出现1次,-1出现2次,1出现0次;

    这说明当排序好后c2=c2+(i-j)*a[i]; 即a[i]在c2中的贡献是比a[i]小的数字个数减去比a[i]数字大的个数乘a[i];

    例如例子中比2大的数只有1个,比2小的数也只有1个那么2的贡献为0;例如数字1;比1大的有两个那么1的贡献为-2*1;

    #include<stdio.h>
    #include<stdlib.h>
    #include <algorithm>
    using namespace std;
    __int64 gcd(__int64 a,__int64 b)
    {
        if(b==0) return a;
        return gcd(b,a%b);
    }
    __int64 a[100005];
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            int i,j;
            __int64 c1,c2,cnt,g;
            c1=c2=0;
            for(i=0;i<n;i++)
            {
                scanf("%I64d",&a[i]);
                c2+=a[i];
            }
            /*for(i=0;i<n;i++)
            {
                for(j=i+1;j<n;j++)
                {
                    if(a[i]>a[j]) c1+=a[i]-a[j];
                    else c1+=a[j]-a[i];
                }
            }*/
            sort(a,a+n);                //
            for(i=0,j=n-1;i<n;i++,j--)  //
            {                           //
                c1+=(i-j)*a[i];         //
            }                           //
            c1*=2;
            cnt=c1+c2;
            g=gcd(cnt,n);
            printf("%I64d %I64d
    ",cnt/g,n/g);
        }
    }
    


  • 相关阅读:
    用DropDownList实现的省市级三级联动
    hcheck 脚本
    转 How To Stop A Running Job Using DBMS_JOB
    转 UTL_FILE Throws ORA-29284 Or ORA-29283 When Attempting To READ File
    转 Monitoring Restore/Recovery Progress
    转 禁用HAIP,cluster_interconnects配错了集群无法启动
    转 LIST INCARNATION OF DATABASE
    转 AIX7.2+11.2.0.4RAC实施
    opatch on-line patch and standby-fisrt patch
    转 Oracle]如何在Oracle中设置Event
  • 原文地址:https://www.cnblogs.com/leejuen/p/5547493.html
Copyright © 2020-2023  润新知