Top Coder SRM 614 DIV 2

250:

没什么说的。
<pre name="code" class="cpp">#include <sstream>

using namespace std;

class MicroStrings
{
public:
	MicroStrings(){}
	~MicroStrings(){}

	string makeMicroString(int A, int D)
	{
		stringstream ss;
		while(A >= 0)
		{
			ss << A;
			A -= D;
		}
		return ss.str();
	}
	/* data */
};


 
 

500:

求最少包含N-2个节点的正方形的最小面积,肯定尽量包含少的点让正方形的面积越小,因此只考虑包含N-2个点的正方形。数据量比较小,直接枚举不在正方形中的两个点,然后求包含剩下N-2个点的最小正方形。一个正方形由左下角的点以及它的边长确定。先确定左下角的点,找到N-2个点中最小的X----minX,最小的Y---minY。设左下角点坐标为(x 1,y 1),要使N-2个点都在正方形内部,必有x 1  < minX, y < minY。要使正方形面积最小,因此左下角的点坐标为(x 1,y 1)=(minX-1, minY-1)。然后确定边长,在N-2个点中最大的X为maxX,y方向最大的Y为maxY。要使正方形包含所有点,必有边长l>max(maxX - x 1,maxY-y 1),要使面积最小,因此去l = max(maxX - x 1,maxY-y 1) + 1。
#include <vector>
#include <memory.h>
#include <math.h>
#include <iostream>
using namespace std;

#define inf 0x7fffffff


class MinimumSquareEasy
{
public:
	MinimumSquareEasy(){}
	~MinimumSquareEasy(){}

	long long minArea(vector <int> x, vector <int> y)
	{
		bool visit[60];
		long long result = -1;
		for(unsigned int i = 0; i < x.size(); i++)
		{
			for(unsigned int j = i + 1; j < x.size(); j++)
			{
				memset(visit, 0, sizeof(visit));
				visit[i] = visit[j] = 1;
				int minX = inf, maxX = -inf, minY = inf, maxY = -inf, x1, y1;
				long long l;
				for(unsigned int k = 0; k < x.size(); k++)
				{
					if(visit[k])
						continue;
					if(x[k] < minX)
						minX = x[k];
					if(x[k] > maxX)
						maxX = x[k];
					if(y[k] < minY)
						minY = y[k];
					if(y[k] > maxY)
						maxY = y[k];
				}

				x1 = minX - 1;
				y1 = minY - 1;
				l = max(maxX - x1, maxY - y1) + 1;
				if(result == -1 || l * l < result)
					result = l * l;
			}
		}

		return result;
	}

	/* data */
};

1000:

由题意可知,在该人的第t步时,他所处的坐标是(t%N, t%M)。可以发现当t等于N、M的最小公倍数时,该人又回到了原点,并开始重复刚才的过程。令C等于lcm(N,M)。则该人所能到的状态由[0,C)确定。令E[X]表示该人首次到达X所用步数的期望,0<=X <=C,由于在每一步该人前进后退的概率都是1/2。因此容易得到

E[X]=1/2(E[X-1] + 1) + 1/2(E[X + 1] + 1) =1/2(E[X-1] + E[X+1]) + 1  (0<X <C)

并且容易知道E[0] = E[C] = 0。即该人首次到原点的步数的期望是0,因为他初始位置就在原点。由上式容易得到

         E[X]= 2E[X-1] - E[X-2] + 1 0<X<C       (1)

发现这是一个递推的式子,我们的目标就是要把这个方程组解出来。注意到E[X]是由它之前的项线性表示的,因此我们用E[1]表示所有的E[X],即我们设E[X] = a[X]E[1] + b[X]。代入上式可以解出:

         a[X]= 2a[X-1] - a[X-2]

         b[X]= 2b[X-1] - b[X-2] - 2  2<X<C

         且容易得到a[0] =0, a[1] = 1, b[0] = 0, b[1] = 0,然后由上述递推公式可以解出a[X], b[X]。 这样对任意X, 

E[X] =a[X]E[1] + b[X]   0<=X < C        (2)

         现在唯一要做的便是求出E[1],就可以求出所有的E[X]了。对公式1应用累加法,容易得到

         E[1]+ E[C-1] = 2(C-1)        (3)

         结合公式3和公式2,容易求出

         E[1]= (2*C - 2 - b[C - 1]) / (a[C-1] + 1)

         这样就可以求E[X]了。
<span style="font-family: Arial, Helvetica, sans-serif;">class TorusSailingEasy</span>
{
public:
	TorusSailingEasy(){}
	~TorusSailingEasy(){}

	double expectedTime(int N, int M, int goalX, int goalY)
	{
		int cnt = N * M / gcd(N, M);
		int goal = -1;
		for(int i = 0; i < cnt; i++)
		{
			if((i % N == goalX) && (i % M == goalY))
				goal = i;
		}
		if(goal == -1)
			return -1.0;

		a[0] = 0;
		a[1] = 1;
		b[0] = 0;
		b[1] = 0;
		for(int i = 2; i < cnt; i++)
		{
			a[i] = 2 * a[i - 1] - a[i - 2];
		}

		for(int i = 2; i < cnt; i++)
		{
			b[i] = 2 * b[i - 1] - b[i - 2] - 2;
		}

		double E = (2 * cnt - 2 - b[cnt - 1]) / 1.0 / (a[cnt - 1] + 1);
		return a[goal] * E + b[goal];
	}

	int gcd(int a, int b)
	{
		if(a < b)
			return gcd(b, a);
		if(b == 0)
			return a;
		return gcd(b, a % b);
	}

private:
	int a[200], b[200];

	/* data */
};






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值