Topcoder SRM 547 DIV1 Level 1: Pillars

本文针对Topcoder上的一道难题进行了解析,提出了两种高效的求解方法,并详细解释了其背后的数学原理及动态规划思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: http://community.topcoder.com/stat?c=problem_statement&pm=12055&rd=14739

题目大意:对所有的1<=x<=X, 1<=y<=Y和给定的w, 求s = sqrt(w*w + (x-y)*(x-y))的平均值。

解题报告:

如果枚举所有可能情况,则时间复杂度为O(X* Y),该题中X和Y分别最大值为100000,显然暴力枚举过不了测试。具体分析发现公式S显然只随着d=y-x在变化,原来的枚举空间中有很多次重复的计算。假设y>x(如果不大于,交换两个数), 则d=1,2,...,K=Y-X 分别有X条;d= K+1, K+2, ..., Y-1分别有X-1,X-2,...,1条; d= -1, -2, ..., -X+1分别有X-1,X-2,...,1条。分别求出d=1,2,。。。,Y-1的各个边长,再求和取平均,即可得最终结果。 时间复杂度为O(max{X,Y }).

 

解法二:动态规划求解

Let's have a look at the sum of all possible  lengthes. Let d(i, j) be the length between two pillars with heights i and j. Then we have the following sum:

    S=d(1,1)+d(1,2)+...+d(1,y)+d(2,1)+d(2,2)+...+d(2,y)+...+d(x,1)+...+d(x,y).

Obviuosly d(i,j)=d(j,i) and d(i-1,j-1)=d(i,j). We can assume that x<=y and  then:

 
    S=d(1,1)+d(1,2)+...+d(1,y)+d(1,2)+d(1,1)+d(1,2)+..+d(1,y-1)+...+d(1,x)+d(1,x-1)+...+d(1,y-x+1).

Let f(n) be the sum d(1,2)+...+d(1,n). Then

    S=f(y)+f(1)+d(2,2)+f(y-1)+f(2)+d(3,3)+f(y-2)+...+f(x-1)+d(x,x)+f(y-x+1).
 
s = sum {f[x] + w + f[y-x+1]} {1<=x<=X, w = d[x,x]}

 

Code

 class Pillars
    {

        public double getExpectedLength(int w, int x, int y)
        {
            double result = 0;
            if (y < x)
            {
                int tmp = y;
                y = x;
                x = tmp;
            }
            int delta = y - x;
            for (int i = 0; i <= delta; i++)
            {
                double z = 1.0 * x;
                result += z * System.Math.Sqrt( 1.0 *w * w + 1.0 * i * i);
            }

            for (int i = delta + 1; i < y; i++)
            {
                double z = 1.0 * (y - i);
                result += z * System.Math.Sqrt(1.0 * w * w + 1.0 * i * i);
            }

            for (int i = 1; i < x; i++)
            {
                double z = 1.0 * (x - i);
                result += z * System.Math.Sqrt(1.0 * w * w + 1.0 * i * i);
            }
            return result/x/y;
        }

        public double getExpectedLength2(int w, int x, int y)
        {
            double[] f = new double[100001];
            int N = System.Math.Max(x, y);
            f[1] = 0;
            for (int i = 2; i <= N; i++)
            {
                double d = distance(w, i - 1);
                f[i] = (f[i - 1] + d);
            }
            double sum = 0;
            for (int i = 1; i <= x; i++)
            {
                sum += f[i] + w + f[y - i + 1];
            }

            return sum / x / y;
        }


        private static double distance(int w, int d)
        {
            double x = 1.0 * w * w + 1.0 * d * d;
            return System.Math.Sqrt(x);
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值