前言
在美团的校招尾声试着投了下,百度应该是没了,就一直挂着,挺揪心的,不过也无所谓了,当作尝试吧。
早上10
点到12
点,做的还行把,总共5
道,ac
了4
道,1
道确实不会😂
题目
争夺地盘
第一题,感觉是白给的,做做循环累加数量即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import java.util.HashSet; import java.util.Scanner; import java.util.Set;
public class Main {
public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int p = in.nextInt(); int q = in.nextInt(); Set<Integer> setA = new HashSet<>(p); for (int i = 0; i < p; i++) { setA.add(in.nextInt()); } int[] B = new int[q]; for (int i = 0; i < q; i++) { B[i] = in.nextInt(); } Set<Integer> r = new HashSet<>(); for (int i = 0; i < q; i++) { if (setA.contains(B[i])) { r.add(B[i]); } } int cA = 0; int cB = 0; for (int i : setA) { if (!r.contains(i)) { cA++; } } for (int i : B) { if (!r.contains(i)) { cB++; } } System.out.println(cA + " " + cB + " " + r.size()); } }
|
不看输入操作,时间复杂度O(p + 2q)=O(p + q)
(应该是这么计算的把😂)
空间复杂度(这里不算数组B
)最好情况下O(Math.min(p,q))
,也就是setA
此时为长度较小的一方,且没有公共的土地序号(r
长度为0
)
最坏情况下O(p + q)
修改大小写
第二题,感觉还是白给,对大小写计数,然后与长度的1/2
相减即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String p = in.next(); int len = p.length(); int upperCount = 0; for (int i = 0; i < len; i++) { if (p.charAt(i) >= 'A' && p.charAt(i) <= 'Z') { upperCount++; } } int lowerCount = len - upperCount; System.out.println(len / 2 - Math.min(lowerCount, upperCount)); } }
|
式子求值
这道花了最多的时间,思路没错
就是刚开始没想到其实可以先开个数组把累计异或的数组求出来,后面直接使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int len = in.nextInt(); int[] array = new int[len]; for (int i = 0; i < len; i++) { array[i] = in.nextInt(); } int[] dp = new int[len + 1]; for (int i = 1; i <= len; i++) { dp[i] = i ^ dp[i - 1]; } int result = 0; for (int i = 0; i < len; i++) { result ^= array[i]; } for (int i = 1; i <= len; i++) { int r = len % i; int c = len / i; if (c % 2 != 0) { result ^= dp[i - 1]; } if (r > 0) { result ^= dp[r]; } } System.out.println(result); } }
|
这题难点就是上面我标的核心过程这段,我们可假设现在有6
个数,也就是说现在要mod1
一直到mod6
比如现在位于第一个数n1
,那么异或的过程就是
n1 ^ (1 % 6) ^ (2 % 6) ^ (3 % 6) ^ (4 % 6) ^ (5 % 6) ^ (6 % 6)
我们可以列出来一个表,如下
|
mod1 |
mod2 |
mod3 |
mod4 |
mod5 |
mod6 |
n1 |
0 |
1 |
1 |
1 |
1 |
1 |
n2 |
0 |
0 |
2 |
2 |
2 |
2 |
n3 |
0 |
1 |
0 |
3 |
3 |
3 |
n4 |
0 |
0 |
1 |
0 |
4 |
4 |
n5 |
0 |
1 |
2 |
1 |
0 |
5 |
n6 |
0 |
0 |
0 |
2 |
1 |
0 |
刚开始的时候我列了这个表,试图从横向来找规律,使得能够在O(1)
时间内得到异或的结果,不过没想出来
卡了一会之后,尝试在纵向上做文章,发现了纵向上数字的规律
首先我们要知道异或,也就是^
这个符号的意思,也就是二进制的两个位相同为0
,不同为1
,也就是
1 ^ 1 == 0, 0 ^ 1 == 1
对于两个相同的数字,他们的二进制表示是一样的,那么异或之后就会为0
OK,回到上边那个表,我们可以每一列进行分析
- 对于
mod1
这一列,结果都是0
,不太好看出规律
- 对于
mod2
这一列,1,3,5
对mod2
的结果是一样的,2,4,6
也是,也就是数据可以分成3
组
- 对于
mod3
这一列,1,4
|2,5
|3,6
对mod3
结果是相同的,也就是数据分成了两组
- 对于
mod4
这一列,1,5
|2,6
|3
|4
对mod4
结果相同,这里3
,4
没有下一个数字与之对应
- 对于
mod5
这一列,1,6
|2
|3
|4
|5
对mod5
结果相同,这里2
,3
,4
,5
没有下一个数字与之对应
- 对于
mod6
这一列,1
|2
|3
|4
|5
|6
对mod6
结果相同,这里每个数都没有没有下一个数字与之对应
那么根据上面的分析,表可以变为
|
mod1 |
mod2 |
mod3 |
mod4 |
mod5 |
mod6 |
n1 |
0 |
1 |
1 |
1 |
1 |
1 |
n2 |
0 |
0 |
2 |
2 |
2 |
2 |
n3 |
0 |
1 |
0 |
3 |
3 |
3 |
n4 |
0 |
0 |
1 |
0 |
4 |
4 |
n5 |
0 |
1 |
2 |
1 |
0 |
5 |
n6 |
0 |
0 |
0 |
2 |
1 |
0 |
没错,每列都一直在重复,比如
第二列1->0
为重复序列
第三列1->2->0
为重复序列
第四列1->2->3->0
为重复序列
第四列1->2->3->4->0
为重复序列
那么结合之前说的异或的性质,如果是偶数次重复且没有剩余元素的话的话,那么本列结果一定为0
,
如果奇数次重复且没有剩余元素,那么只要计算一次重复的序列
如果存在剩余元素,那么再单独异或然后加入结果集即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Main { public static void main(String[] args) { for (int i = 1; i <= len; i++) { int r = len % i; int c = len / i; if (c % 2 != 0) { result ^= dp[i - 1]; } if (r > 0) { result ^= dp[r]; } } } }
|
刚开始没使用dp
来提前计算累计的异或的话,还是超时,使用之后,就可以通过了。
公司管理
这题完全看不懂啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,最后没时间做了…🤣
矩阵游戏
这题放在第二部分的卷子,刚开始看感觉很难,但是试了试其实不难,递归回到2x2
的情况即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int a = in.nextInt(); int b = in.nextInt(); int c = in.nextInt(); int n = in.nextInt(); while (n > 0) { int x = in.nextInt() - 1; int y = in.nextInt() - 1; int[][] twoXTwo = { {0, a}, {b, c} }; int r = dfs(x, y, twoXTwo); System.out.println(r); n--; } }
static int dfs(int x, int y, int[][] twoXTwo) { if (x < 2 && y < 2) { return twoXTwo[x][y]; } int len = 2; int max = Math.max(x, y); while (len <= max) { len = len * 2; } int div = len / 2; int result; if (x >= div && y >= div) { result = twoXTwo[1][1] + dfs(x - div, y - div, twoXTwo); } else if (x < div && y >= div) { result = twoXTwo[0][1] + dfs(x, y - div, twoXTwo); } else { result = twoXTwo[1][0] + dfs(x - div, y, twoXTwo); } return result % 1000000000; } }
|
后记
总体上感觉很好,难度适中,下次一定还来😂