目录
A - Leyland Number
题目描述
给你两个整数 A A A和 B B B( 2 ≤ A , B ≤ 9 2 \le A,B \le 9 2≤A,B≤9),输出 A A A的 B B B次方与 B B B的 A A A次方之和。
思路:幂运算
public static void solve() throws IOException {
int a = readInt(), b = readInt();
printWriter.println((int)Math.pow(a, b) + (int)Math.pow(b, a));
}
B - Longest Palindrome
题目描述
给你一个字符串 S S S,求出其中的最长回文字符串的长度。
思路:模拟
- 由于数据范围比较小,用双层
for
直接遍历出那个回文字符串的长度即可,最短为1。
public static void solve() throws IOException {
String s = readString();
int res = 0;
for (int i = 0; i < s.length(); i++) {
for (int j = i + 1; j < s.length() + 1; j++) {
if (new StringBuilder(s.substring(i, j)).reverse().toString().equals(s.substring(i, j))) {
res = Math.max(res, j - i);
}
}
}
printWriter.println(res);
}
C - Slot Strategy 2 (Easy)
题目描述
有三个卷轴,每个卷轴上的符号分别是由数字组成的长度为 m m m的字符串 S i S_i Si,每个卷轴上都有一个按钮,同一时刻你只可以按下一个按钮,对于某一时刻 t t t,当这个按钮被按下后,卷轴上会显示 S i S_i Si上的第 ( t m o d m ) (t \ mod \ m) (t mod m)个字符(下标从 0 0 0开始),你需要求出最小的时间 t t t,使得三个卷轴上的字符相等,如果它们不可能相等,输出 − 1 -1 −1。
输入样例
4 1234 1234 1234
输出样例
8
样例解释: 0 0 0时刻按下第 1 1 1个卷轴, 4 4 4时刻按下第 2 2 2个卷轴, 8 8 8时刻按下第 3 3 3个卷轴,总共耗时 8 8 8。
思路:读题+模拟+枚举
- 由于数据范围比较小,直接枚举出三个卷轴出现相等字符的时间 t t t。但由于无法确定先按下哪个卷轴才能使 t t t最小,所以对于每个卷轴,遍历 m ∗ 3 m*3 m∗3的范围即可,如果还是无法让每个卷轴上的字符相等,输出 − 1 -1 −1。
public static void solve() throws IOException {
int m = readInt();
String s1, s2, s3;
s1 = readString(); s2 = readString(); s3 = readString();
int res = Integer.MAX_VALUE;
for (int i = 0; i < m * 3; i++) {
for (int j = 0; j < m * 3; j++) {
for (int k = 0; k < m * 3; k++) {
if (i != j && i != k && j != k) {
if (s1.charAt(i % m) == s2.charAt(j % m) && s1.charAt(i % m) == s3.charAt(k % m)) {
res = Math.min(res, Math.max(i, Math.max(j, k)));
}
}
}
}
}
printWriter.println(res == Integer.MAX_VALUE ? -1 : res);
}
D - Relative Position
题目描述
总共有 N N N个人在一个二维平面上,编号为 1 ∼ N 1 \sim N 1∼N,现在给你 M M M对他们之间的坐标关系,形式为 { A i A_i Ai, B i B_i Bi, X i X_i Xi, Y i Y_i Yi },即对于 A i A_i Ai来说, B i B_i Bi的坐标为 { A i A_i Ai的 x x x 坐标 + X i X_i Xi, A i A_i Ai的 y y y 坐标 + Y i Y_i Yi }。请你求出这 N N N个人的坐标,如果某个人的坐标无法确定或者不唯一,则输出undecidable
。
思路:dfs+图论
- 根据输入的坐标关系,很容易联想到建图,那我们就建图!而且是双向图。
- 他们的坐标关系可以用一个字符串来表示。
- 用一个数组 s t st st存下信息不唯一的点。
static class Edge {
int to, pe;
String w;
public Edge(int to, int pe, String w) {
this.to = to;
this.pe = pe;
this.w = w;
}
}
static int n, m, idx = 1;
static int[] head;
static Edge[] edges;
static long inf = Long.MAX_VALUE;
static Pair[] pairs;
static boolean[] st;
public static void solve() throws IOException {
int n = readInt(), m = readInt();
pairs = new Pair[n + 1];
st = new boolean[n + 1];
head = new int[n + 1];
Arrays.setAll(pairs, p -> new Pair());
edges = new Edge[m * 2 + 10];
for (int i = 1; i <= n; i++) {
pairs[i] = new Pair(inf, inf);// 先全部初始化为无穷大,这样用于确定还没有确定信息
}
pairs[1].first = 0; pairs[1].second = 0;// 初始化坐标原点
for (int i = 1; i <= m; i++) {
int a = readInt(), b = readInt(), c = readInt(), d = readInt();
// a->b的值为整数,b->a的值为负数
add(a, b, c + "," + d); add(b, a, -c + "," + -d);
}
dfs(1);
for (int i = 1; i <= n; i++) {
// 这个点没有确定信息或者信息不唯一
if (pairs[i].first == inf && pairs[i].second == inf || st[i]) {
printWriter.println("undecidable");
} else {
printWriter.println(pairs[i].first + " " + pairs[i].second);
}
}
}
public static void dfs(int u) {
for (int i = head[u]; i != 0; i = edges[i].pe) {
int to = edges[i].to;
String w = edges[i].w;
String[] strings = w.split(",");
int t1 = Integer.valueOf(strings[0]), t2 = Integer.valueOf(strings[1]);// 距离
long p = pairs[u].first, q = pairs[u].second;
if (pairs[to].first == inf && pairs[to].second == inf) {// 第一次确定坐标
pairs[to].first = p + t1;
pairs[to].second = q + t2;
dfs(to);
} else {
long m1 = p + t1, m2 = q + t2;
//第一下确定的坐标信息与第二次确定的坐标信息不一致,则坐标信息不唯一
if (pairs[to].first != m1 || pairs[to].second != m2) {
st[to] = true;
}
}
}
}
public static void add(int a, int b, String c) {
edges[idx] = new Edge(b, head[a], c);
head[a] = idx++;
}
E - Somen Nagashi
题目描述
有编号为 1 ∼ N 1 \sim N 1∼N的 N N N个人从左到右站成一排进行一场执行 M M M次的活动,对于每个活动,都有一个时间 T i T_i Ti和一捆质量为 W i W_i Wi的面条,站在那排的第一个人将获得者捆面条,然后这个人要在 T i + S i T_i+S_i Ti+Si之后才能再次回到自己原来的位置,求在 M M M次活动之后每个人获得的面条质量。
输入样例
3 5 1 1 3 2 10 100 4 100 10000 10 1000 1000000000 100 1000000000 1
输出样例
101 10 1000
思路:优先队列
- 用两个优先队列分别维护已在队伍中的人和将要回到队伍中的人的时间,感觉这题不如前两题。
public static void solve() throws IOException{
int n = readInt(), m = readInt();
// 维护已在队伍中的人
PriorityQueue<Integer> people = new PriorityQueue<>();
// 维护将要回到队伍中的人的时间
PriorityQueue<Pair> back = new PriorityQueue<>(new Comparator<Pair>() {
@Override
public int compare(Pair o1, Pair o2) {
return o1.first < o2.first ? -1 : 1;
}
});
for (int i = 1; i <= n; i++) people.offer(i);
long[] total = new long[n + 1];
for (int i = 1; i <= m; i++) {
int t = readInt(), w = readInt(), s = readInt();
// 队头的人能够重新回到队伍
while (back.size() > 0 && back.peek().first <= t) {
people.offer(back.poll().second);
}
// 队伍中有人,拿上面条后进入 back队列
if (people.size() > 0) {
int p = people.poll();
total[p] += w;
back.offer(new Pair(t + s, p));
}
}
for (int i = 1; i <= n; i++) {
printWriter.println(total[i]);
}
}