A—Edge Checker 2
题目大意
给你一棵树,输入两个 \(1 - 15\) 的数 \(a, b\),求 \(a\) 是否是 \(b\) 老爹父亲
这颗树如图 :
题目解法
超级无敌暴力法(wu
一种最最最简单粗暴的方法就是把所有的关系存起来,然后每次输入都在这些里面搜一遍,有的话输出 Yes
,没有的话输出 No
。
由于过于粗暴,作者就不写了(wu
正常的解法
看到这棵树可以发现一个普通树的规律:
左孩子编号等于该节点编号乘二,
右孩子编号等于该节点编号乘二加一。
又因为如果有关系的话肯定是 \(a\) 是 \(b\) 的父亲,不可能是 \(b\) 是 \(a\) 的父亲 整时空穿越了。
所以答案就浮出水面了,我们只需要判断如下两个式子如果成立一个就是 Yes
,都不成立就是 No
。
标程
#include <bits/stdc++.h>
using namespace std;
int a, b;
int main() {
cin >> a >> b;
if (b == a * 2) {
cout << "Yes" << endl;
} else if (b == a * 2 + 1) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
B—Longest Uncommon Prefix
题目大意
给你一个长为 \(N\) 的字符串 \(S\) ,让你求出对于每一个 \(i\),求出最大的\(j(i + j \le N)\),满足:
\[\forall k \le j, S_k = S_{k + i} \]题目解法
暴力
看到题目第一眼想到的是枚举每一个i,j,与k,暴力求出答案。
代码:
看正解去!
正解
看样例解释就能发现,我们就能发现
其实我们只需要枚举 \(i\) 与 \(k\) 就可以了,因为实际上k的最大值就是j的最大值。
具体的,拿样例来说:
当 \(i=1\) , \(S_1 \ne S_2\) , \(S_2 \ne S_3\) , … , \(S_5 \ne S_6\) , 所以最大值为 \(j=5\)。
当 \(i=2\) , \(S_1 \ne S_3\) , \(S_2 = S_4\) 所以最大值为 \(j=1\)。
当 \(i=3\) , \(S_1 \ne S_4\) , \(S_2 \ne S_5\) , \(S_3 =S_6\) 所以最大值为 \(j=2\)。
当 \(i=4\) , \(S_1 = S_5\) 所以最大值为 \(j=0\)。
当 \(i=5\) , \(S_1 \ne S_6\) 所以最大值为 \(j=1\)。
标程
#include <bits/stdc++.h>
using namespace std;
int n;
string s;
int main() {
cin >> n;
cin >> s;
s = ' ' + s;
for (int i = 1; i < n; i++) {
int ans = 0;
for (int j = 1; j + i <= n; j++) {
if (s[j] != s[j + i]) {
ans = j;
} else {
break;
}
}
cout << ans << endl;
}
return 0;
}
C—Brutmhyhiizp
题目大意
Atcoder 中有肥肠多的题目,他们都按以下规则编号:
A, B, ... , AA, AB, ..., BA, ... , AAA, ...
现在要求你求出所给编号的题目是第几题。
解法
暴力
一个一个数,这样代码很难写,而且还拿不到满分,肥肠的笨蛋,我也不写代码了(wu
正解
相信对于数学战斗力爆表的你们来说,肯定能一下就想到这道题跟进制有关系.
实际上这就是一个27进制的体现:
空=0,A=1,B=2,......,Z=26
所以实际上这道题就是一道进制转换题,瞬间没难度了。
该不会还有人不会进制转换吧
标程
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
string s;
LL ans; // 不开longlong见祖宗!
int main() {
cin >> s;
ans = 0;
for (int i = 0; i < s.size(); i++) {
ans *= 26;
ans += s[i] - 'A' + 1;
}
cout << ans << endl;
return 0;
}
D—Change Usernames
题目大意
有 \(N\) 个homo网友,他们都想换个网名,可是不能有任何一个瞬间有俩人网名一样,而且呢,服务器只能同时改变一个网友的网名。
他就问你,如果你是服务器你能安排改变网名的顺序并符合以上条件吗,是则输出 Yes
,否则输出 No
。
解法
首先,我们一看到这个题:一个玩意儿变另外一个玩意儿,这不是图吗。的确,这道题使用图解,但是,不是在网友之间连线,是在网名之间连线。
???
实际上我们要做的就是是整个离散化,然后把网名整成数字,然后扔进图里。
我们就直接忽略网友,在网名之间连线。
是不是茅塞顿开了。
那扔进图里了,要干啥?
我们先看看第二个样例:
Input
3
a b
b c
c a
Output
No
我们把图画出来后发现是这样子的:
graph LR A((a)) --> B((b)) B --> C((c)) C --> A我们发现它成环了。
这样,在环中,无论先改哪个,都会与已有网名重叠。
所以实际上这道题就是判这张图有没有环,有的话输出 No
,没有的话输出 Yes
。(不要搞反了)
那判环要用什么算法呢?
DFS!
想出来了吗?答案就在上面,框一下就出来了。
标程
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n;
string s[N];
string t[N];
int cnt;
string hsh_hdl[2 * N];
map<string, int> hdl_hsh;
vector<int> G[2 * N];
int color[2 * N];
bool dfs(int u) {
color[u] = 0;
for (int v: G[u]) {
if (color[v] == 0) {
return false;
} else if (color[v] == -1) {
if (!dfs(v)) {
return false;
}
}
}
color[u] = 1;
return true;
}
int main() {
memset(color, -1, sizeof color);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i] >> t[i];
if (!hdl_hsh[s[i]]) {
cnt++;
hdl_hsh[s[i]] = cnt;
hsh_hdl[cnt] = s[i];
}
if (!hdl_hsh[t[i]]) {
cnt++;
hdl_hsh[t[i]] = cnt;
hsh_hdl[cnt] = t[i];
}
G[hdl_hsh[s[i]]].push_back(hdl_hsh[t[i]]);
}
bool ans = true;
for (int i = 1; i <= cnt; i++) {
if (color[i] == -1) {
if (!dfs(i)) {
ans = false;
break;
}
}
}
if (ans) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
至于后面4题,小编不会了,原谅一下。
标签:Atcoder,cnt,int,hsh,color,ABC285,hdl,网名,赛后 From: https://www.cnblogs.com/explosive-OIer/p/atcoder_abc285_saihouzongjie.html