ABC350A-F题解

14 篇文章 0 订阅


下面的内容不包括题目翻译,要想获取题目翻译,请参照 这篇教程 来获取题目翻译。

A

题目

只需要判断 S S S 是否在 ABC001ABC349 范围内即可。

可以使用字符串之间的大小关系来快速通过此题。

AC Code(CPP):

#include <iostream>
using namespace std;
string s;
string t = "ABC350";

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> s;
	if (s < t && s != "ABC316" && s >= "ABC001") {
		cout << "Yes";
	}
	else {
		cout << "No";
	}
	return 0;
}

AC Code(Python):

s = input()
print(('No', 'Yes')[s != 'ABC316' and 'ABC001' <= s <= 'ABC349'])

B

题目

C++ 中,可以通过使用一个布尔数组来判断这颗牙齿是否被拔除。而在 Python 中,可以通过集合实现。如果集合里面有这个元素,说明这颗牙齿被拔掉了,否则,说明这颗牙齿还在。

AC Code(CPP):

#include <iostream>
using namespace std;
int n, q;
bool vis[2010];

int main() {
	cin >> n >> q;
	while (q--) {
		int t;
		cin >> t;
		if (vis[t]) {
			n++;
			vis[t] = 0;
		}
		else {
			n--;
			vis[t] = 1;
		}
	}
	cout << n << '\n';
	return 0;
}

AC Code(Python):

n, q = [int(i)for i in input().split()]
a = set([])
t = [int(i)for i in input().split()]

for k in t:
    if k in a:
        n += 1
        a.remove(k)
    else:
        n -= 1
        a.add(k)


print(n)

C

题目

答案的特性: i = a i i=a_i i=ai。根据这个特性,我们可以对于不在对应位置上的每一个数,让正确的数和它交换。由于数一共只有 N N N 个,交换最多 N − 1 N-1 N1 次,所以可以符合条件。

注意 python 的下标问题。

AC Code(CPP):

#include <iostream>
#include <queue>
using namespace std;
int n;
int a[200100];
int p = -1;
int idx[200100];
queue<pair<int, int>> q;

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) {
		idx[a[i]] = i;
	}
	int cnt = 0;
	
	for (int i = 1; i <= n; i++) {
		if (a[i] != i) {
			cnt++;
			q.push({min(idx[i], i), max(idx[i], i)});
			int tmp = idx[i];
			swap(idx[a[i]], idx[i]);
			swap(a[i], a[tmp]);
			
		}
	}
	cout << cnt << '\n';
	while (!q.empty()) {
		cout << q.front().first << ' ' << q.front().second << '\n';
		q.pop();
	}
	return 0;
}

AC Code(Python)

n = int(input())
a = [int(i) - 1 for i in input().split()]
idx = [0 for i in range(n)]
for i in range(n):
    idx[a[i]] = i
ans = []
for i in range(n):
    if a[i] != i:
        ans.append([min(idx[i], i), max(idx[i], i)])
        temp = idx[i]
        idx[a[i]], idx[i] = idx[i], idx[a[i]]
        a[i], a[temp] = a[temp], a[i]
print(len(ans))
for i in ans:
    print('%d %d' % (i[0] + 1, i[1] + 1))

D

题目

这个问题须要一点图论知识。

我们可以发现,对于一群人,如果这群人是“联通”的,那么就一定可以将这一群人操作成一个“完全图”。所以对于一群联通的人,操作次数就等于这张图成为完全图的边数(点数乘以点数减一)减去已有的朋友关系。

通过并查集来查找联通块,并快速地解决这个问题。

注意 Python 中递归层数的限制

AC Code(CPP):

#include <iostream>
#define int long long
using namespace std;
int n, m;
int u[200100], v[200100];
int f[200100];
long long cnt[200100], cnt1[200100];
int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);}
bool vis[200100];
long long ans;

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) f[i] = i;
	for (int i = 1; i <= m; i++) {
		cin >> u[i] >> v[i];
		f[find(v[i])] = find(u[i]);
	}
	for (int i = 1; i <= m; i++) {
		cnt[find(u[i])]++;
	}
	for (int i = 1; i <= n; i++) {
		cnt1[find(i)]++;
	}
	for (int i = 1; i <= n; i++) {
		if (find(i) == i)
			ans += cnt1[i] * (cnt1[i] - 1ll) / 2ll - cnt[i];
	}
	cout << ans << '\n';
	return 0;
}

AC Code(Python):

import sys
sys.setrecursionlimit(998244353)
n, m = [int(i) for i in input().split()]
f = [i for i in range(n + 3)]


def find(x):
    if x != f[x]:
        f[x] = find(f[x])
    return f[x]


a = []
for i in range(m):
    a.append([int(i) for i in input().split()])
    a[i][1] -= 1
    a[i][0] -= 1
    f[find(a[i][1])] = find(a[i][0])
cnt = [0] * (n + 3)
cnt1 = [0] * (n + 3)
for i in range(m):
    cnt[find(a[i][0])] += 1
for i in range(n):
    cnt1[find(i)] += 1
ans = 0
for i in range(n):
    if find(i) == i:
        ans += (cnt1[i] * (cnt1[i] - 1) // 2) - cnt[i]
print(ans)

E

题目

可以想到使用搜索加上记忆化来解决这个问题。设 f ( x ) f(x) f(x) 是把 x x x 变为 0 0 0 的代价,这个值为操作一期望代价和操作二期望代价的最小值,其中操作一期望代价很好算,就是 f ( ⌊ x A ⌋ ) + X f(\lfloor \frac{x}{A} \rfloor) + X f(⌊Ax⌋)+X。而操作二期望代价是这个式子:

f ( x ) = 1 6 f ( ⌊ 1 x ⌋ ) + 1 6 f ( ⌊ x 2 ⌋ ) + 1 6 f ( ⌊ x 3 ⌋ ) + 1 6 f ( ⌊ x 4 ⌋ ) + 1 6 f ( ⌊ x 5 ⌋ ) + 1 6 f ( ⌊ x 6 ⌋ ) + Y f(x)=\frac16f(\lfloor \frac1x \rfloor) + \frac16f(\lfloor \frac x2 \rfloor) + \frac16f(\lfloor \frac x3 \rfloor) + \frac16f(\lfloor \frac x4 \rfloor) + \frac16f(\lfloor \frac x5 \rfloor) + \frac16f(\lfloor \frac x6 \rfloor)+Y f(x)=61f(⌊x1⌋)+61f(⌊2x⌋)+61f(⌊3x⌋)+61f(⌊4x⌋)+61f(⌊5x⌋)+61f(⌊6x⌋)+Y

这个式子看似要无线递归,但是通过移项可以得到这个东西:

f ( x ) = f ( ⌊ x 2 ⌋ ) + f ( ⌊ x 3 ⌋ ) + f ( ⌊ x 4 ⌋ ) + f ( ⌊ x 5 ⌋ ) + f ( ⌊ x 6 ⌋ ) + Y 5 f(x)=\frac{f(\lfloor \frac x2 \rfloor) + f(\lfloor \frac x3 \rfloor) + f(\lfloor \frac x4 \rfloor) + f(\lfloor \frac x5 \rfloor) + f(\lfloor \frac x6 \rfloor)+Y}5 f(x)=5f(⌊2x⌋)+f(⌊3x⌋)+f(⌊4x⌋)+f(⌊5x⌋)+f(⌊6x⌋)+Y

编码就十分简单。

时间复杂度分析

首先,枚举第一种情况是 log ⁡ A ( N ) \log_A(N) logA(N) 的时间复杂度,可以视为没有。

第二种情况:

由于 ⌊ ⌊ N a ⌋ b ⌋ = ⌊ N a b ⌋ \lfloor\frac{\lfloor \frac Na \rfloor}b\rfloor=\lfloor \frac N{ab}\rfloor baN=abN,所以讨论 4 4 4 6 6 6 的情况会被 2 2 2 3 3 3 剪枝。而我们要计算的是 ⌊ N m ⌋ \lfloor \frac Nm\rfloor mN,所以 m m m 可以被表示为 2 x 3 y 5 z 2^x3^y5^z 2x3y5z,而时间复杂度也只有 log ⁡ 2 ( N ) log ⁡ 3 ( N ) log ⁡ 4 ( N ) \log_2(N)\log_3(N)\log_4(N) log2(N)log3(N)log4(N)

AC Code(CPP):

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a, x, y;
map<long long, double> m;
double f(int now) {
	if (now == 0) return 0;
	if (m[now]) return m[now];
	double sum = y;
	for (int i = 2; i <= 6; i++) {
		sum += f(now / i) + y;
	}
	m[now] = min({sum / 5.0, f(now / a) + x});
	return min({sum / 5.0, f(now / a) + x});
}
signed main() {
	scanf("%lld%lld%lld%lld", &n, &a, &x, &y);
	printf("%.16lf", f(n));
	return 0;
}

AC Code(Python):

n, a, x, y = [int(i)for i in input().split()]
m = {}


def f(now):
    if now == 0:
        return 0
    if now in m.keys():
        return m[now]
    cnt = y
    for i in range(2, 7):
        cnt += f(now // i) + y
    m[now] = min(cnt / 5, f(now // a) + x)
    return m[now]


print(f(n))

F

题目

可以通过递归函数计算。 f ( l , r , p ) f(l, r, p) f(l,r,p) 负责打印从 l l l r r r 的字符。如果 p p p 等于 0 0 0,那么是正序打印,否则,是倒序打印。每遇到一个括号,就打印括号内的东西,打印顺序反过来。每一对对应的括号可以通过预处理得到。可以预先将每一个大小写预处理,就不用再打印时判断了。(如果括号层数为奇数就要翻转大小写。)或者在打印时判断。

于是可以在 O ∣ S ∣ O|S| OS 的时间复杂度内求解问题。

AC Code(CPP):

#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
char s[500100];
int n;
void init() {
	string s1;
	cin >> s1;
	for (int i = 0; i < (int)s1.size(); i++) {
		s[i + 1] = s1[i];
	}
	n = s1.size();
}
int idx[500100], idx1[500100];

void f(int l, int r, int p) {
	if (p == 0) {
		for (int i = l; i <= r; i++) {
			if (s[i] == '(') {
				f(i + 1, idx[i] - 1, 1);
				i = idx[i];
			}
			else {
				cout << s[i];
			}
		}
	}
	else {
		for (int i = r; i >= l; i--) {
			if (s[i] == ')') {
				f(idx1[i] + 1, i - 1, 0);
				i = idx1[i];
			}
			else {
				cout << s[i];
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	init();
	int cnt = 0;
	stack<int> st;
	for (int i = 1; i <= n; i++) {
		if (s[i] == '(') {
			cnt++;
			st.push(i);
		}
		else if (s[i] == ')') {
			cnt--;
			idx[st.top()] = i;
			idx1[i] = st.top();
			st.pop();
		}
		else {
			if (cnt % 2) {
				if ('a' <= s[i] && s[i] <= 'z') {
					s[i] -= 'a';
					s[i] += 'A';
				}
				else {
					s[i] -= 'A';
					s[i] += 'a';
				}
			}
		}
	}
	f(1, n, 0);
	return 0;
}

AC Code(Python):

import sys
sys.setrecursionlimit(998244353)
s = input()
cnt = 0
idx = [0] * (len(s) + 1)
idx1 = [0] * (len(s) + 1)
stack = []


def f(l, r, p):
    if p == 0:
        temp = l
        while temp <= r:
            if s[temp] == '(':
                f(temp + 1, idx[temp] - 1, 1)
                temp = idx[temp] + 1
            else:
                print(s[temp], end='')
                temp += 1
    else:
        temp = r
        while temp >= l:
            if s[temp] == ')':
                f(idx1[temp] + 1, temp - 1, 0)
                temp = idx1[temp] - 1
            else:
                if 'a' <= s[temp] <= 'z':
                    print(chr(ord(s[temp]) - 32), end='')
                else:
                    print(chr(ord(s[temp]) + 32), end='')
                temp -= 1


for i in range(len(s)):
    if s[i] == '(':
        cnt += 1
        stack.append(i)
    elif s[i] == ')':
        cnt -= 1
        idx[stack[len(stack) - 1]] = i
        idx1[i] = stack[len(stack) - 1]
        stack.pop(len(stack) - 1)
f(0, len(s) - 1, 0)

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
{"pid":-1,"layers":[{"component":{"id":"21de350a-9acc-4fc1-9290-b53b0f3e6939","name":"方块翻牌器","alias":"Cubeflop","version":"v1.0.0","thumbnail":"images/widgets/tools/tool/cubeflop.png","width":450,"height":60,"pnode":{"type":"tool","pnode":{"type":"tools"}},"option":{"suffix":"/ppm","duration":300,"prefix":"NO₂","decimals":1,"textStyle":{"fontSize":30,"color":"rgba(61, 156, 255, 1)","textShadow":{"show":false,"x":0,"y":0,"value":14,"color":"rgba(15, 146, 255, 1)"},"colorSecondary":"rgba(221, 221, 221,1)","fontWeight":"bold"},"backgroundColor":"rgba(8, 21, 39, 1)"},"source":[{"name":"default","source":{"type":"mysql","filter":{"isFilter":false,"filterId":-1},"isAutoUpdate":true,"autoUpdateTime":6,"mapping":[{"name":"value","required":true,"description":"值","type":"number","mapping":"value"}],"static":[{"value":1234.56}],"api":{"sourcesId":-1,"requestType":"GET","requestHeader":{"token":null},"getParam":"","postParam":{},"requestUrl":"","cookie":false,"postMethods":"raw"},"mysql":{"sourcesId":"ea93b0c0-ff44-11ed-a2ea-8fe1718b947a","database":"jxjk","sql":"SELECT*from device_data_update WHERE id =12","sources":{"id":"ea93b0c0-ff44-11ed-a2ea-8fe1718b947a","name":"测试","description":"","host":"192.168.2.66","port":3306,"user":"root","password":"123"}},"elasticsearch":{"sourcesId":-1,"query":{"index":"_all"}},"mongodb":{"sourcesId":-1,"query":{},"collection":-1},"csv":{}}}]},"id":"3f8433b2-1902-4141-8b17-fc36a9a1001c","name":"图层-17-副本(6)","type":"layer","left":29.091,"top":775,"width":450,"height":50,"widthHeightLink":false,"zIndex":8,"locked":false,"visible":true,"opacity":1,"rotate":0,"rotateX":0,"rotateY":0,"mixBlendMode":null,"background":{"color":"rgba(255, 255, 255, 0)"},"border":{"width":0,"color":"#2ed64a","style":"solid"},"radius":{"value":0},"shadow":{"show":false,"color":"rgba(132, 132, 132, 1)","value":5,"ambiguity":10,"x":3,"y":2},"padding":{"value":0},"animation":"","animations":[],"baseLeft":1220,"baseTop":515,"randomRgbaColor":"rgba(255,255,255,0.2)","rightX":506.364,"rightY":781.81}]} 在JavaScript中只留下value一个字段、
06-13

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值