其他分享
首页 > 其他分享> > 归档:220807 | 开门水题:STL 系列模板题

归档:220807 | 开门水题:STL 系列模板题

作者:互联网

所有题目都在橙到绿之间。梦回小学。


UVA [101] - The Blocks Problem

用一个前驱数组和一个后继数组维护一个类似于链表的结构。

然后每次更改根据题意要求,依次递进地更改结点的前驱 / 后继即可。

namespace XSC062 {
using namespace fastIO;
const int maxn = 35;
char t, t1;
int n, x, y;
int fa[maxn], so[maxn];
inline void moto(int a, int b) {
	so[fa[a]] = 0;
	int x = a, y;
	while (so[x]) {
		y = x;
		x = so[x];
		so[y] = 0;
	}
	while (x != a) {
		y = x;
		x = fa[x];
		fa[y] = 0;
	}
	x = b;
	while (so[x]) {
		y = x;
		x = so[x];
		so[y] = 0;
	}
	while (x != b) {
		y = x;
		x = fa[x];
		fa[y] = 0;
	}
	fa[a] = b;
	so[b] = a;
	return;
}
inline void moer(int a, int b) {
	so[fa[a]] = 0;
	int x = a, y;
	while (so[x]) {
		y = x;
		x = so[x];
		so[y] = 0;
	}
	while (x != a) {
		y = x;
		x = fa[x];
		fa[y] = 0;
	}
	x = b;
	while (so[x]) 
		x = so[x];
	fa[a] = x;
	so[x] = a;
	return;
}
inline void pito(int a, int b) {
	so[fa[a]] = 0;
	int x = b;
	while (so[x]) {
		y = x;
		x = so[x];
		so[y] = 0;
	}
	while (x != b) {
		y = x;
		x = fa[x];
		fa[y] = 0;
	}
	fa[a] = b;
	so[b] = a;
	return;
}
inline void pier(int a, int b) {
	so[fa[a]] = 0;
	int x = b;
	while (so[x]) 
		x = so[x];
	fa[a] = x;
	so[x] = a;
	return;
}
inline bool check(int x, int y) {
	while (fa[x])
		x = fa[x];
	while (fa[y])
		y = fa[y];
	return x != y;
}
int main() {
	scanf("%d", &n);
	do {
		scanf("%1s%*s", &t);
		if (t == 'q')
			break;
		scanf("%d %*1s%1s%*s %d", &x, &t1, &y);
		if (!check(++x, ++y))
			continue;
		if (t == 'm') {
			if (t1 == 'n')
				moto(x, y);
			else moer(x, y);
		}
		else {
			if (t1 == 'n')
				pito(x, y);
			else pier(x, y);
		}
	} while (1);
	for (int i = 1; i <= n; ++i) {
		printf("%d:", i - 1);
		if (!fa[i]) {
			x = i;
			do {
				printf(" %d", x - 1);
				x = so[x];
			} while (x);
		}
		putchar('\n');
	}
	return 0;
}
} // namespace XSC062

UVA [1594] - Ducci Sequence

发现题目保证最多循环 \(10^3\) 次,考虑暴力模拟 \(10^3\) 次,若中间任意时刻整个数组为 \(0\),则输出 ZERO,否则输出 LOOP

优化:使用 std::mapstd::set 存储某个序列是否出现过(可以采用 std::vector 实现),若出现过则输出 LOOP,不过不优化时间上也完全没有问题,故没有优化。

namespace XSC062 {
const int maxn = 25;
int T, n;
int a[maxn], b[maxn];
inline int abs(int x) {
	return x >= 0 ? x : -x;
}
int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; ++i)
			scanf("%d", &a[i]);
		for (int _t = 1; _t <= 1000; ++_t) {
			a[n + 1] = a[1];
			bool flag = 1;
			for (int i = 1; i <= n; ++i) {
				b[i] = abs(a[i] - a[i + 1]);
				if (b[i])
					flag = 0;
			}
			if (flag)
				goto ZEROOOOO;
			memcpy(a, b, sizeof(a));
		}
		puts("LOOP");
		continue;
		ZEROOOOO:
			puts("ZERO");
	}
	return 0;
}
} // namespace XSC062

CodeChef [SGARDEN] - Garden Game

题意:有若干个环,求其大小的最小公倍数,结果对 \(10^9+7\) 取模。

一个典型的错解是,使用 \(x \times y \div \gcd(x,y)\) 与逆元 依次 求最小公倍数,因为取模会改变因子,从而使最大公约数的值 unexpected。

一个好的解决方案是模拟人工计算,将每一个 \(x\) 分解质因数并计算每个质因子最多的出现次数,最后相乘即可。

#define int long long
namespace XSC062 {
using namespace fastIO;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int T, n, x, cnt, res, tmp;
int a[maxn], u[maxn], p[maxn], tot[maxn];
inline int qkp(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1)
			(res *= x) %= mod;
		(x *= x) %= mod;
		y >>= 1;
	}
	return res;
}
inline int max(int x, int y) {
	return x > y ? x : y;
}
int main() {
	read(T);
	while (T--) {
		cnt = 0;
		res = 1;
		read(n);
		for (int i = 1; i <= n; ++i) {
			read(a[i]);
			u[i] = p[i] = tot[i] = 0;
		}
		for (int i = 1; i <= n; ++i) {
			if (p[i])
				continue;
			++cnt;
			x = i;
			do {
				p[x] = cnt;
				x = a[x];
				++u[cnt];
			} while (x != i);
		}
		for (int i = 1; i <= cnt; ++i) {
			for (int j = 2; j <= u[i]; ++j) {
				if (u[i] % j)
					continue;
				tmp = 0;
				while (!(u[i] % j)) {
					++tmp;
					u[i] /= j;
				}
				tot[j] = max(tot[j], tmp);
			}
		}
		for (int i = 1; i <= n; ++i)
			(res *= qkp(i, tot[i])) %= mod;
		printf("%lld\n", res);
	}
	return 0;
}
} // namespace XSC062
#undef int

UVA [400] - Unix ls

可以预先计算出共有几行几列。设最大长度为 \(m\),则列数 \(l = \lfloor 62 \div m \rfloor\),行数 \(c = \lceil n \div l \rceil\)。

为什么是 \(62\) 呢?因为有一列要少输出 \(2\) 个空格,为了方便,我们加上这 \(2\) 个空格使得其与其他列统一。

然后模拟行、列增加的过程(枚举行列或枚举字符串均可),最后输出即可。

namespace XSC062 {
const int maxn = 505;
std::string t;
std::string s[maxn];
std::string op[maxn][maxn];
int n, mx, l, c, m, tc, tl;
inline int max(int x, int y) {
	return x > y ? x : y;
}
int main() {
	while (std::cin >> m) {
		mx = 0;
		n = 0;
		std::getline(std::cin, t);
		for (int i = 1; i <= m; ++i) {
			std::getline(std::cin, t);
			std::stringstream temp(t);
			while (temp >> s[++n])
				mx = max(mx, s[n].length());
			--n;
		}
		n = m;
		std::sort(s + 1, s + n + 1);
		l = 62 / (mx + 2);
		c = (n + l - 1) / l;
		tc = tl = 1;
		for (int i = 1; i <= c; ++i) {
			for (int j = 1; j <= l; ++j)
				op[i][j].clear();
		}
		for (int i = 1; i <= n; ++i) {
			op[tc++][tl] = s[i];
			if (tc == c + 1) {
				++tl;
				tc = 1;
			}
		} 
		for (int i = 1; i <= 60; ++i)
			putchar('-');
		putchar('\n');
		for (int i = 1; i <= c; ++i) {
			for (int j = 1; j <= l; ++j) {
				if (op[i][j].size())
					std::cout << op[i][j];
				for (int k = s[(j - 1) * c + i].size() + 1;
					 k <= mx; ++k) {
					putchar(' ');
				}
				if (!op[i][j + 1].size())
					break;
				putchar(' ');
				putchar(' ');
			}
			putchar('\n');
		}
	}
	return 0;
}
} // namespace XSC062

UVA [1593] - Alignment of Code

一个简单的对齐输出。简单到我认为没有可讲的。

namespace XSC062 {
const int maxn = 1e4 + 5;
int n, lin;
int mx[maxn];
std::string t, t1;
std::vector<std::string> s[maxn];
inline int max(int x, int y) {
	return x > y ? x : y;
}
int main() {
	while (std::getline(std::cin, t)) {
		++lin;
		s[lin].clear();
//		s[lin].shrink_to_fit(); 
		std::stringstream temp(t);
		int cnt = 0;
		while (temp >> t1) {
			s[lin].push_back(t1);
			++cnt;
			mx[cnt] = max(mx[cnt], t1.length());
		}
	}
	for (int i = 1; i <= lin; ++i) {
		for (int j = 0; j < (int)s[i].size(); ++j) {
			std::cout << s[i][j];
			for (int k = s[i][j].size() + 1;
				 k <= mx[j + 1] + 1; ++k)
				putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}
} // namespace XSC062

Codeforces [727B] - Bill Total Value

难点在于判断一个数为整数还是浮点数。

令某个存储了一整个数的字符串为 \(s\)。

不难发现,当 \(|s|\le 3\) 时,\(s\) 一定表示一个整数。

否则,若 \(s\) 表示整数,则位数 \(>3\),至少分一段,此时 \(s_{|s|-4}\) 为 .(从 \(0\) 开始存储)。

其余情况,\(s\) 为浮点数。

namespace XSC062 {
using namespace fastIO;
bool f;
char inp;
std::string s, t;
int x, y, tx, ty, cnt;
int main() {
	std::getline(std::cin, s);
	s.push_back('#');
	std::stringstream temp(s);
	while (temp >> inp) {
		if (inp >= '0' && inp <= '9') {
			std::string tmp;
			tx = ty = 0;
			do tmp.push_back(inp); while (temp >> inp
				&& ((inp >= '0' && inp <= '9') || inp == '.'));
			if (tmp.size() <= 3)
				tx = std::stoi(tmp);
			else if (tmp[tmp.size() - 4] == '.') {
				for (auto i : tmp) {
					if (i >= '0' && i <= '9')
						tx = tx * 10 + i - '0';
				}
			}
			else {
				for (int i = 0; i < (int)tmp.size() - 2; ++i) {
					if (tmp[i] >= '0' && tmp[i] <= '9')
						tx = tx * 10 + tmp[i] - '0';
				}
				ty = (tmp[tmp.size() - 2] - '0') * 10
					 + tmp[tmp.size() - 1] - '0';
			}
			x += tx;
			y += ty;
		}
	}
	x += y / 100;
	y %= 100;
	if (!x)
		t.push_back('0');
	while (x) {
		t.push_back((x % 10) + '0');
		x /= 10;
	}
	std::reverse(t.begin(), t.end());
	cnt = t.length();
	for (const auto &i : t) {
		putchar(i);
		if (!((--cnt) % 3)) {
			if (cnt)
				putchar('.');
		}
	}
	if (y) {
		putchar('.');
		if (y < 10)
			putchar('0');
		std::cout << y;
	}
	return 0;
}
} // namespace XSC062

标签:std,水题,fa,STL,220807,int,while,so,maxn
来源: https://www.cnblogs.com/XSC062/p/16560333.html