ABC342A-E题解

14 篇文章 0 订阅

A

题目

这个 A 题为什么是平时 B 题的分值?

统计每一个字母的出现次数,找到出现次数为 1 1 1 的字母,输出它的位置,完事。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
string s;
int cnt[100100];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> s;
	int len = s.size();
	for (int i = 0; i < len; i++) {
		cnt[s[i] - 'a']++;
	}
	for (int i = 0; i < 26; i++) {
		if (cnt[i] == 1) {
			for (int j = 0; j < len; j++) {
				if (s[j] == i + 'a') {
					cout << j + 1;
					return 0;
				}
			}
		}
	}
	return 0;
}

B

题目

对于每一个寻问,找到这两个数的位置,输出值较小的那个数的坐标,完事。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int n, q;
int p[100100];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> p[i];
	}
	cin >> q;
	while (q--) {
		int l ,r;
		cin >> l >> r;
		int idx1, idx2;
		for (int i = 1; i <= n; i ++) {
			if (p[i] == l) idx1 = i;
			if (p[i] == r) idx2 = i;
		}
		cout << (idx1 <  idx2 ? l : r) << '\n';
	}
	return 0;
}

C

题目

此题容易被误解成并查集,但是第一个样例就可以 hack 普通并查集做法。

我们直接记录原来字串中那些字母要被替换成另外的字母,一开始所有字母都要被替换成自己,每出现一个替换关系,比如把 a a a 替换成 b b b,我们就寻找原来要替换成 a a a 的字母,将其替换成 b b b,最后输出时在原字母中进行替换即可。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int n, q;
string s;
int f[30];

int main() {
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	cin >> n >> s;
	for (int i = 0; i < 26; i++) f[i] = i;
	cin >> q;
	while (q--) {
		string u, v;
		cin >> u >> v;
		int a = u[0] - 'a', b = v[0] - 'a';
		for (int i = 0; i < 26; i++) if (f[i] == a) f[i] = b;
	}
	for (int i = 0; i < n; i ++) cout << char('a' + f[s[i] - 'a']);
	return 0;
}

D

题目

对于一个完全平方数,我们将其分解质因数,每一个质因数的个数一定是偶数,这个不难理解。

那么如果我们将一个完全平方数乘上另一个完全平方数,结果是完全平方数,这个应该也在你的理解范围里。

根据上一个定理,我们可以推导出:如果一个完全平方数除以另一个完全平方数,如果结果是整数,那么结果也是一个完全平方数。

现在,关键的定理来了:

如果两个数 a a a b b b,他们可以分解为 k ⋅ p k\cdot p kp l ⋅ q l \cdot q lq,其中 k , p , l , q k,p,l,q k,p,l,q 为整数,且 p p p q q q 为完全平方数, p p p q q q 尽可能大,如果 a ⋅ b a\cdot b ab 为完全平方数,那么 k k k 等于 l l l

让我们证明一下,对于结果,除以 p p p q q q 后,剩下 k ⋅ l k\cdot l kl,那么结果一定是一个完全平方数,这个定理可以根据上面说的推导出来。而 k k k l l l 不是完全平方数,只能说明 k k k 等于 l l l。请自行理解,如果 k k k 不等于 l l l,哪里会产生矛盾。

我们就可以预处理出每一个数分解掉所有可被分解的完全平方数,统计剩下每一个数字的个数。对于每一个数字,可以与其他和这个数字相等的组成一对,加上其他数字的个数。对于 0 0 0,加上 2 ( n − 1 ) 2(n-1) 2(n1),因为这个 0 0 0 可以与其他数字组成一组,其他数字也可以与这个数字组成一组。设一共有 x x x 0 0 0,最后答案要减去 x ( x − 1 ) x(x-1) x(x1),因为 0 0 0 0 0 0 之间的连边被重复算了。最后答案除以 2 2 2,去掉重复算的组数,输出就完事了。

特别注意:答案要开长整形!

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
long long n, a[200100];
long long ans;
map<long long, long long> cnt;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (long long i = 1; i <= n; i ++) cin >> a[i];
	for (long long i = 1; i <= n; i ++) {
		long long tmp = sqrt(a[i]);
		bool vis = 1;
		while (vis) {
			vis = 0;
			for (long long j = 2; j <= tmp; j++) {
				if (a[i] % (j * j) == 0) {
					a[i] /= (j * j);
					vis = 1;
					break;
				}
			}
		}
	}
	for (long long i = 1; i <= n; i ++) {
		cnt[a[i]]++;
	}
	for (long long i = 1; i <= n; i ++) {
		if (a[i] == 0) ans += (n - 1) * 2;
		else ans += cnt[a[i]] - 1;
	}
	ans -= cnt[0] * (cnt[0] - 1);
	cout << ans / 2;
	return 0;
}

E

题目

要算每一个点到终点的时间,可不可以把所有边逆转方向,再从终点跑一遍最短路?

我们得到在时间限制下每一条路线最后一班车的时间,再跑一遍迪杰斯特拉算法,终点的时间为无穷大,然后让每一个点到达的时间尽量大,去找下一条边时,要乘坐时间不能超过当前时间的列车。如果第一班车都比当前时间晚,就不能乘坐。如果没有跑到一个点,就说明这个点不能到达终点。

注意:要开长整形,由于精度问题,建议全开长整形。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
long long n, m;
struct edge{
	long long u, v, w, l, d, k, nxt;
	long long get(long long t) {
		if (t < l + w) return -1;
		return l + min(k - 1, (t - l - w) / d) * d;
	}
};
edge ed[400100];
long long edcnt, head[200100];
void addedge(long long l, long long d, long long k, long long u, long long v, long long w){
	edcnt++;
	ed[edcnt].u = u;
	ed[edcnt].v = v;
	ed[edcnt].w = w;
	ed[edcnt].l = l;
	ed[edcnt].d = d;
	ed[edcnt].k = k;
	ed[edcnt].nxt = head[u];
	head[u] = edcnt;
}
struct node {
	int x;
	long long dis;
	node(int x_, long long dis_) {
		x = x_;
		dis = dis_;
	}
};
bool operator <(node a, node b) {
	return a.dis < b.dis;
}

long long dis[514114];
long long ans[200100];
void dijkstra() {
	priority_queue<node> pq;
	pq.push(node(n, 0x7f7f7f7f7f7f7f7f));
	while (!pq.empty()) {
		node now = pq.top();
		pq.pop();
		if (ans[now.x] > now.dis) continue;
		for (int i = head[now.x]; i; i = ed[i].nxt) {
			int v = ed[i].v;
			long long t = ed[i].get(now.dis);
			if (t != -1 && ans[v] < t) {
				ans[v] = t;
				pq.push(node(v, t));
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		long long l, d, k, c, a, b;
		cin >> l >> d >> k >> c >> a >> b;
		addedge(l, d, k, b, a, c);
	}
	for (long long i = 1; i <= n; i++) {
		ans[i] = -1;
	}
	ans[n] = 0x7f7f7f7f7f7f7f7f;
	dijkstra();
	for (int i = 1; i < n; i++) {
		if (ans[i] != -1) cout << ans[i] << '\n';
		else cout << "Unreachable\n";
	}
	return 0;
}
  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值