目录
- [A - ab](#A - ab)
- [B - A^A](#B - A^A)
- [C - Number Place](#C - Number Place)
- [D - Good Tuple Problem](#D - Good Tuple Problem)
A - ab
题目描述
判断一个给定的字符串是否存在字符
a
和字符b
相邻。
java
public static void solve() throws IOException{
int a = readInt();
String s = readString();
boolean f = s.contains("ab") || s.contains("ba");
printWriter.println(f ? "Yes" : "No");
}
B - A^A
题目描述
给定一个整数
B
,判断是否存在一个整数A
,使得 A A = B A^A=B AA=B,如果存在,输出 A A A,否则输出 − 1 -1 −1。思路:枚举
java
public static void solve() throws IOException{
long a = readLong();
boolean f = false;
for (int i = 1; i <= 100; i++) {
long q = 1;
for (int j = 1; j <= i; j++) {
q *= i;
}
if (q == a) {
printWriter.println(i);
f = true;
break;
}
if (q > a) break;
}
if (!f) {
printWriter.println(-1);
}
}
C - Number Place
题目描述
给定义一个 9 × 9 9 \times 9 9×9 的二维矩阵,判断这个矩阵是否满足以下全部条件,如果满足输出
Yes
,否则输出No
。
- 1 ∼ 9 1 \sim 9 1∼9的数字分别都在每行每列出现一次。
- 将该二维矩阵按顺序拆为 9 9 9 个 3 × 3 3 \times 3 3×3 的二维矩阵后, 1 ∼ 9 1 \sim 9 1∼9的数字分别都在每个矩阵出现一次。
思路:模拟+技巧
- 先判断每行每列是否满足条件。
- 再判断每个小二维矩阵是否满足条件。
java
public static void solve() throws IOException{
int[][] map = utils.nextIntArray(9, 9);
boolean f = true;
// 判断行
n = 9;
for (int i = 1; i <= n; i++) {
Set<Integer> set = new HashSet<>();
for (int j = 1; j <= n; j++) {
set.add(map[i][j]);
}
if (set.size() != 9) f = false;
}
// 判断列
for (int i = 1; i <= n; i++) {
Set<Integer> set = new HashSet<>();
for (int j = 1; j <= n; j++) {
set.add(map[j][i]);
}
if (set.size() != 9) f = false;
}
// 判断小圈
int[] x = new int[] {1, 4, 7}, y = new int[] {3, 6, 9};
for (int a = 0; a < 3; a++) {// 控制行
for (int b = 0; b < 3; b++) {// 控制列
Set<Integer> set = new HashSet<>();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// 处于该小圈范围内
if (i >= x[a] && i <= y[a] && j >= x[b] && j <= y[b]) {
set.add(map[i][j]);
}
}
}
if (set.size() != 9) {
f = false;
break;
}
}
}
printWriter.println(f ? "Yes" : "No");
}
D - Good Tuple Problem
题目描述
给定一个数组 S S S 和一个数组 T T T,长度都为 M M M。问是否存在一个长度为 N N N 的
01
数组 X X X,使得 X S i ≠ X T i ( 1 ≤ i ≤ N ) X_{S_i} \neq X_{T_i}(1 \leq i \leq N) XSi=XTi(1≤i≤N),如果存在,输出Yes
,否则输出No
。输入样例
3 3 1 2 3 2 3 1
输出样例
No
思路:并查集+技巧
- 这题仅问我们是否存在,而不要求求出序列 X X X,那么可以使用并查集,将 X X X 存在矛盾的两个位置记录下来,关键在于怎么维护存在矛盾的两个位置。
- 使用 N N N作为偏移量,每遍历到一对 S i S_i Si 和 T i T_i Ti 时,可以理解为都是在染色。
① 如果 p [ S i ] ≠ p [ T i ] p[S_i] \neq p[T_i] p[Si]=p[Ti],那么就分别更新他们的父节点为 f i n d ( T i + n ) find(T_i + n) find(Ti+n) 和 f i n d ( S i + n ) find(S_i + n) find(Si+n),表示 S i S_i Si不能和 f i n d ( T i + n ) find(T_i + n) find(Ti+n)染同一种颜色, T i T_i Ti不能和 f i n d ( S i + n ) find(S_i + n) find(Si+n)染同一种颜色。
② 如果 p [ S i ] = p [ T i ] p[S_i] = p[T_i] p[Si]=p[Ti],假设为 p p p,此时 S i S_i Si 不能和 p p p 染同一种颜色, T i T_i Ti不能和 p p p 染同一种颜色,但是 S i S_i Si 又不能和 T i T_i Ti 染同一种颜色,但是总共又只能染两种颜色,这时就出现了矛盾。
java
static int[] p;
public static void solve() throws IOException{
int n = readInt(), m = readInt();
int[] s = new int[m + 1], t = new int[m + 1];
for (int i = 1; i <= m; i++) s[i] = readInt();
for (int i = 1; i <= m; i++) t[i] = readInt();
p = new int[2 * n + 1];
for (int i = 1; i <= 2 * n; i++) p[i] = i;
boolean f = true;
for (int i = 1; i <= m; i++) {
int a = s[i], b = t[i];
int pa = find(a), pb = find(b);
if (pa == pb) {// 出现矛盾
f = false;
break;
}
p[pa] = find(b + n);
p[pb] = find(a + n);
}
printWriter.println(f ? "Yes" : "No");
}
public static int find(int x) {
if (x != p[x]) {
p[x] = find(p[x]);
}
return p[x];
}