一名苦逼的OIer,想成为ACMer

Iowa_Battleship

CF Round #516 (Div. 2, by Moscow Team Olympiad)

前言:依旧菜,\(A\)\(4\)题,不过这次上蓝了挺开心的。

A. Make a triangle!

Description

给出\(3\)根木棍,希望用它们拼成三角形,可以将其中的某些木棍增长,求至少需要增长多少才能拼成一个三角形。

Solution

水题,答案就是最长的木棍长度减去剩下两根木棍的长度和再\(+1\),如果为负则输出\(0\)(即本来就能拼成三角形)。

#include<cstdio>
using namespace std;
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline void sw(int &x, int &y)
{
	int z = x;
	x = y;
	y = z;
}
int main()
{
	int a, b, c;
	a = re();
	b = re();
	c = re();
	if (a < b)
		sw(a, b);
	if (a < c)
		sw(a, c);
	if (b < c)
		sw(b, c);
	if (b + c > a)
		printf("0");
	else
		printf("%d", a - b - c + 1);
}

B. Equations of Mathematical Magic

Description

给出\(a\),求方程\(a - (a\oplus x) - x = 0\)的解的个数(\(\oplus\)\(xor\)操作)

Solution

找规律,样例很贴心的给出最大数,于是我大力猜结论,核对机房大佬的表后发现正确,非常愉快。
结论:设\(s\)\(a\)在二进制下\(1\)的个数,则答案就是\(2^s\)
然而并不会证明

#include<cstdio>
using namespace std;
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
int main()
{
	int a, s, i, t = re();
	while (t--)
	{
		s = 0;
		a = re();
		for (i = 30; ~i; i--)
			if (a & (1 << i))
				s++;
		printf("%d\n", 1 << s);
	}
	return 0;
}

C. Oh Those Palindromes

Description

给你一个字符串,你可以任意改变串中字符的位置,求构造一个有最多回文子串的字符串。

Solution

构造题,一开始想的很复杂,然后打到一半,机房大佬突然说,只要将相同的字符扔在一起就好了。。
所以这题就是一个\(sort\)的事。。因为我是在打到一半的代码临时改的,所以直接在计数数组上构造了。

#include<cstdio>
using namespace std;
const int N = 1e5 + 10;
const int M = 300;
struct dd{
	int s;
	char c;
};
dd a[M];
int mp[M], l;
char an[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline void re_l()
{
	char c = getchar();
	for (; c < 'a' || c > 'z'; c = getchar());
	for (; c >= 'a' && c <= 'z'; c = getchar())
	{
		if (!mp[c])
		{
			a[++l].c = c;
			a[l].s = 1;
			mp[c] = l;
		}
		else
			a[mp[c]].s++;
	}
}
int main()
{
	int i, k = 0, j;
	re();
	re_l();
	for (i = 1; i <= l; i++)
		for (j = 1; j <= a[i].s; j++)
			an[++k] = a[i].c;
	for (i = 1; i <= k; i++)
		putchar(an[i]);
	return 0;
}

D. Labyrinth

Description

一个迷宫,部分格子有障碍物不能走,而你向左和向右走的步数有限制,向上和向下则没有限制,求你一共能到达多少个格子。

Solution

为了到达某个格子是最优情况(剩余向左向右的步数尽量多),可以使用双端队列\(+BFS\),将向上或下走的插入队首,向左或向右的插入队尾,正常\(BFS\)即可。
因为我和机房大佬们一开始想复杂了,我打了\(3.4k\),结果我打挂了。。最后\(1\)分钟的时候,就想着交个暴力算了,于是爆改代码到\(1.6k\),离结束\(15s\)的时候\(pp\)了。
结果因为我恰好改的就是双端队列\(+BFS\)(一开始想的也是基于这个)暴力搜,结果\(A\)了。。。
因为临时爆改,代码很冗长,\(BFS\)里的两个\(if\)和一个\(for\)其实可以合在一起,凑合着看吧。

#include<cstdio>
#include<deque>
using namespace std;
const int N = 2010;
struct dd{
	int x, y, mx, my;
};
dd X, Y;
int a[N][N], b[N][N], mo_x[2] = {1, -1}, mo_y[2] = {0, 0}, n, m, s;
deque<dd>q;
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline void re_l(int i)
{
	int k = 0;
	char c = getchar();
	for (; c != '.' && c != '*'; c = getchar());
	for (; c == '.' || c == '*'; c = getchar())
	{
		a[i][++k] = c == '*' ? -1 : 0;
		b[i][k] = a[i][k];
	}
}
int main()
{
	int i, j, s = 0;
	n = re();
	m = re();
	X.x = re();
	X.y = re();
	X.mx = re();
	X.my = re();
	for (i = 1; i <= n; i++)
		re_l(i);
	a[X.x][X.y] = 1;
	q.push_back(X);
	while (!q.empty())
	{
		X = q.front();
		q.pop_front();
		Y = X;
		for (i = 0; i < 2; i++)
		{
			Y.x = X.x + mo_x[i];
			if (!a[Y.x][Y.y] && Y.x > 0 && Y.x <= n && Y.y > 0 && Y.y <= m)
			{
				a[Y.x][Y.y] = 1;
				q.push_front(Y);
			}
		}
		if (X.mx > 0)
		{
			Y = X;
			Y.y--;
			Y.mx--;
			if (!a[Y.x][Y.y] && Y.x > 0 && Y.x <= n && Y.y > 0 && Y.y <= m)
			{
				a[Y.x][Y.y] = 1;
				q.push_back(Y);
			}
		}
		if (X.my > 0)
		{
			Y = X;
			Y.y++;
			Y.my--;
			if (!a[Y.x][Y.y] && Y.x > 0 && Y.x <= n && Y.y > 0 && Y.y <= m)
			{
				a[Y.x][Y.y] = 1;
				q.push_back(Y);
			}
		}
	}
	for (i = 1; i <= n; i++)
		for (j = 1; j <= m; j++)
			if (a[i][j] > 0)
				s++;
	printf("%d", s);
	return 0;
}

posted on 2018-10-14 21:06  Iowa_Battleship  阅读(141)  评论(0编辑  收藏  举报

导航