ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-08-08 00:32:47  阅读:146  来源: 互联网

标签:std 水题 fa STL 220807 int while so maxn


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


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有