Topcoder SRM 639 (Div.2)

A.ElectronicPetEasy

【题意】一个数st1开始,每次加p1,一共加t1次,另外一个数st2开始,每次加p2,一共加t2次,输入的数均小于1000,问这两个数有没有可能相等,有可能输出“Easy”,否则输出“Difficult”

【解释】显然列出两个循环即可,1000*1000也不会超时

const string dif="Difficult";
const string eas="Easy";
class ElectronicPetEasy
{
	public:
	string isDifficult(int st1, int p1, int t1, int st2, int p2, int t2)
	{
		int i,j,k;
		int m1=st1+p1*(t1-1);
		int m2=st2+p2*(t2-1);
		for (i=st1;i<=m1;i+=p1)
		{
			for (j=st2;j<=m2;j+=p2)
			{
				if (i==j) return dif;
			}
		}
		return eas;
	}
};

B.AliceGameEasy

【题意】从1到n,爱丽丝取出几个数累加为x,桐人取出几个数累加为y,给出x和y,问爱丽丝做少取了多少个数(不可能时输出-1)。

【解释】贪心算法

先判断x+y=n*(n+1)/2,能否求出整数n,不能求出来 或者 求出的n不是整数 那么输出-1就好喽

既然求出n了,就让爱丽丝从最大的数开始取,n,n-1,n-2...直到存在k ,使得刚好n+(n-1)+(n-1)+...+(n-k+1)>=x("刚好"的意思是n+(n-1)+(n-1)+...+(n-k)<x),答案就是k。

class AliceGameEasy
{
	public:
	long long findMinimumValue(long long x, long long y)
	{
		LL i,j,k;
		LL dt=(x+y)*8+1;
		LL sqr_dt=(LL)(sqrt(dt));
		if (sqr_dt*sqr_dt!=dt) return -1;
		sqr_dt--;
		if (sqr_dt%2) return -1;
		LL n=sqr_dt/2;
		LL ans=0;
		while (x>0)
		{
			x-=n;
			n--;
			ans++;
		}
		return ans;
	}
};

C.BoardFoldingDiv2

【题意】给出一个01矩阵(最多50*50)(就是题目说的纸),现在要折叠这个矩阵,折叠要满足:

1.平行于某条边折叠

2.要沿相邻两列数字之间折叠

3.折叠后下方的数字与上方的数字相等

现在问有多少种折叠方法,(其中折叠后如果是同一块矩阵区间则算同一种方法)

【解释】显然是可以将行与列分开求,求只按行折叠的方法数ansr,和只按列折叠的方法数ansc,最后ansr*ansc就是答案。

由于按行和按列求的方法相同,下面以按列举例。

出题人相当良心,只给了50*50的规模,而且最重要的是只有0和1,那么将每列的01串视为一个二进制数,用long long存完全能存下,我们存到c[]数组中。

大致思路:枚举右界,如果右界可行的话(需要预处理),再枚举左界,如果左界也可行的话,就算是一个解。

这是预处理:设right[i]=1表示从右开始折叠,能折叠到i,即折叠后第i+1~n-1个数(数的编号是0到n-1)全都消失掉了。当然right[i]=0时表示不能折叠到第i个数。

然后枚举左界,right[k]=1时,枚举左界i,用left[i]表示从左开始折叠,能折叠到i(与right[]是相同的思路,只是变了一下方向)。

算法是O(n3)的

typedef long long LL;
int n,m;
LL r[55],c[55];
int ansr,ansc,lef[55],rig[55];
class BoardFoldingDiv2
{
	public:

	int howMany(vector <string> paper)
	{
		int i,j,k;
		memset(r,0,sizeof(r));
		memset(c,0,sizeof(c));
		ansr=ansc=0;
		n=paper.size();
		m=paper[0].size();

		for (i=0;i<n;i++)
		{
			for (j=0;j<m;j++)
			{
				r[i]=r[i]*2+paper[i][j]-‘0‘;
				c[j]=c[j]*2+paper[i][j]-‘0‘;
			}
		}
		/*对每一横行操作*/
	 	memset(rig,0,sizeof(rig));
		rig[n-1]=1;
		for (i=n-2;i>=0;i--)
		{
			for (j=1;i+j<n&&i-j+1>=0;j++)
			{
				if (r[i+j]==r[i-j+1])
				{
					if (rig[i+j])
					{
						rig[i]=1;
						break;
					}
				}
				else break;
			}
		}
		for (k=n-1;k>=0;k--)//枚举右界
		{
			if (rig[k]==0) continue;//如果右界不可达,continue
			memset(lef,0,sizeof(lef));
			lef[0]=1; ansr++;
			for (i=1;i<=k;i++)//枚举左界
			{
				for (j=1;i+j-1<=k&&i-j>=0;j++)//判断左界是否可达
				{
					if (r[i+j-1]==r[i-j])
					{
						if (lef[i-j])//如果left[i-j]可达 并且 正好能沿数i与数i-1间折叠
						{
							lef[i]=1;//设为可达后跳出
							break;
						}
					}
					else break;
				}
				if (lef[i]!=0) ansr++;
			}
		}

	 	/*对每一列操作*/
	 	memset(rig,0,sizeof(rig));
		rig[m-1]=1;
		for (i=m-2;i>=0;i--)
		{
			for (j=1;i+j<m&&i-j+1>=0;j++)
			{
				if (c[i+j]==c[i-j+1])
				{
					if (rig[i+j])
					{
						rig[i]=1;
						break;
					}
				}
				else break;
			}
		}

		for (k=m-1;k>=0;k--)
		{
			if (rig[k]==0) continue;
			memset(lef,0,sizeof(lef));
			lef[0]=1; ansc+=min(1,lef[0]*rig[k]);
			for (i=1;i<=k;i++)
			{
				for (j=1;i+j-1<=k&&i-j>=0;j++)
				{
					if (c[i+j-1]==c[i-j])
					{
						if (lef[i-j])
						{
							lef[i]=1;
							break;
						}
					}
					else break;
				}
				if (lef[i]!=0) ansc++;
			}
		}
		return ansr*ansc;
	}
};
时间: 2024-08-12 10:45:50

Topcoder SRM 639 (Div.2)的相关文章

TopCoder SRM 639 Div.2 500 AliceGameEasy

题意: 一个游戏有n轮,有A和B比赛,谁在第 i 轮得胜,就获得 i 分,给出x,y,问A得x分,B得y分有没有可能,如果有,输出A最少赢的盘数 解题思路: 首先判断n(n+1)/2 = (x+y)是否有解,即是否存在n为整数,使得所有分数的和加起来为x+y,即判断n2+n-2(x+y)=0,存在整数解, 根据二次方程的根为(-1±Δ)/2 为整数,其中Δ=√(1+8(x+y)) , 即判断1+8(x+y)是否能开方以及Δ是否为奇数(如果Δ为偶数,则根不是整数) 如果前面条件满足,在通过贪心,从

TopCoder SRM 639 Div.2 500 AliceGameEasy --乱搞

题意: 一个游戏有n轮,有A和B比赛,谁在第 i 轮得胜,就获得 i 分,给出x,y,问A得x分,B得y分有没有可能,如果有,输出A最少赢的盘数. 解法: 这题是我傻逼了,处理上各种不优越,要使n*(n+1)/2 >= 10^12, n为10^6是不够的,要开大一点,总是细节地方不注意. 做法很简单,先用map或者其他什么东西判断x+y是否为某个n*(n+1)/2, 如果不是,那肯定为-1,再就是x=0有可能要单独考虑,然后就是选一些数凑成x,由于要最少,那么从大的开始凑起,可以暴力地凑,也可以

TopCoder SRM 634 Div.2[ABC]

TopCoder SRM 634 Div.2[ABC] ACM 题目地址: TopCoder SRM 634 赛后做的,感觉现场肯定做不出来Orz,简直不能多说. Level One-MountainRanges[水题] 题意: 问序列中有几个完全大于旁边的峰. 分析: 傻逼题,不多说. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: one.cpp * Create Date: 2014-09-26 21:01:23 * Desc

TopCoder SRM 628 DIV 2

250-point problem Problem Statement    Janusz is learning how to play chess. He is using the standard chessboard with 8 rows and 8 columns. Both the rows and the columns are numbered 0 through 7. Thus, we can describe each cell using its two coordina

TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization &amp; Codeforces 839 E

传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相加,含有n个不同变量的式子的最大值. 另外限制了每一个变量的最大最小值R[i]和L[i]和所有变量之和的最大值Max. n<=13 题外话: 刚开始做这道题的时候,感觉意外眼熟? codeforces 839 E(此题的退化版):http://codeforces.com/contest/839/pro

[topcoder]SRM 633 DIV 2

第一题,http://community.topcoder.com/stat?c=problem_statement&pm=13462&rd=16076 模拟就可以了. #include <vector> #include <algorithm> using namespace std; class Target { public: vector <string> draw(int n) { vector<string> result(n,

[topcoder]SRM 646 DIV 2

第一题:K等于1或者2,非常简单.略.K更多的情况,http://www.cnblogs.com/lautsie/p/4242975.html,值得思考. 第二题:http://www.cnblogs.com/lautsie/p/4245242.html BFS和DFS都可以,注意的是,写的时候,可以往que里几个东西一起扔,就不用建立对象了.也可以直接用二维矩阵记录blocked和visited. 剪枝什么的,最基本的是发现其实在步数限制的情况下,棋盘就是有界的了. 第三题:http://ap

Topcoder SRM 648 (div.2)

第一次做TC全部通过,截图纪念一下. 终于蓝了一次,也是TC上第一次变成蓝名,下次就要做Div.1了,希望div1不要挂零..._(:зゝ∠)_ A. KitayutaMart2 万年不变的水题. #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map&

TopCoder SRM 596 DIV 1 250

body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } Problem Statement      You have an array with N elements. Initially, each element is 0. You can perform the following operations: Increment operation: