20230907 携程笔试AK
先mark一下,笔试结束后发题解
===========分割线================
t1
题目:找到n个数中相邻的两位之和不是素数的个数。
/**
* 先找出所有的素数对,然后dfs
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
LinkedList<Integer>[] next = new LinkedList[n];
for (int i = 1; i <= n; ++i) {
next[i - 1] = new LinkedList<>();
for (int j = 1; j <= n; ++j) {
if (i != j && checkPrime(i + j)) {
next[i - 1].add(j - 1);
}
}
}
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += dfs(n - 1, i, next, new boolean[n]);
}
System.out.println(sum);
}
static int dfs(int cnt, int cur, LinkedList<Integer>[] next, boolean[] vis) {
if (cnt == 0) {
return 1;
}
int sum = 0;
vis[cur] = true;
for (int num : next[cur]) {
if (!vis[num]) {
sum += dfs(cnt - 1, num, next, vis);
}
}
vis[cur] = false;
return sum;
}
static boolean checkPrime(int n) {
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return true;
}
return false;
}
t2.这题写复杂了,不用分成四个象限
题目:找到以you为三个点组成的直角三角形
/**
* 对于每个点,如果属于'you'中的一个字符,比如说是'y',以它为直角,然后再找到它左边‘o’,上边的点'u'的个数相乘+左边'u'与上边'o'的个数相乘的个数
* 同样的,需要找到其余三个象限(左边+下边,右边+上边,右边+下边)相加即可
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int[][][] dp = new int[n + 1][m + 1][3];
char[] c = new char[]{'y', 'o', 'u'};
//构造
for (int i = 0; i < n; ++i) {
String s = in.next();
for (int j = 0; j < s.length(); ++j) {
for (int k = 0; k < 3; ++k) {
dp[i + 1][j + 1][k] = dp[i + 1][j][k] + dp[i][j + 1][k] - dp[i][j][k] + (c[k] == s.charAt(j) ? 1 : 0);
}
}
}
long sum = 0;
int[][] dir = new int[4][3];
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int target = isTargetChar(dp, i, j);
if (target == -1) continue;
for (int k = 0; k < 3; ++k) {
dir[0][k] = dp[i][j - 1][k] - dp[i - 1][j - 1][k];//左边k字符的个数
dir[1][k] = dp[i - 1][j][k] - dp[i - 1][j - 1][k];//上边k字符的个数
dir[2][k] = dp[n][j][k] - dp[i][j][k] - dp[n][j - 1][k] + dp[i][j - 1][k];//下边k字符的个数
dir[3][k] = dp[i][m][k] - dp[i][j][k] - dp[i - 1][m][k] + dp[i - 1][j][k];//右边k字符的个数
}
//lu
sum += (long) dir[0][(target + 1) % 3] * dir[1][(target + 2) % 3] + (long) dir[1][(target + 1) % 3] * dir[0][(target + 2) % 3];
//ld
sum += (long) dir[0][(target + 1) % 3] * dir[2][(target + 2) % 3] + (long) dir[2][(target + 1) % 3] * dir[0][(target + 2) % 3];
//ru
sum += (long) dir[3][(target + 1) % 3] * dir[1][(target + 2) % 3] + (long) dir[1][(target + 1) % 3] * dir[3][(target + 2) % 3];
//rd
sum += (long) dir[3][(target + 1) % 3] * dir[2][(target + 2) % 3] + (long) dir[2][(target + 1) % 3] * dir[3][(target + 2) % 3];
}
}
System.out.println(sum);
}
static int isTargetChar(int[][][] dp, int x, int y) {
for (int i = 0; i < 3; ++i) {
int cnt = dp[x][y][i] + dp[x - 1][y - 1][i] - dp[x - 1][y][i] - dp[x][y - 1][i];
if (cnt != 0) return i;
}
return -1;
}
t3:
可以对一个数+1,但是同时需要对一个数-1,计算将所有数移到到[l,r]的代价
/**
* 就是需要将不在[l,r]范围内的数移到[l,r]范围内,所以首先需要计算,平均数在不在[l,r]范围内,
* 然后只需要计算需要将超过r的数移到r,和小于l的数移动到l的最大步数即可。
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for (int i = 0; i < t; ++i) {
int n = in.nextInt();
//不加long 只能过85%
long l = in.nextInt();
long r = in.nextInt();
long[] arr = new long[n];
long sum = 0;
long high = 0;
long low = 0;
for (int j = 0; j < n; ++j) {
arr[j] = in.nextInt();
sum += arr[j];
if (arr[j] < l) {
low += l - arr[j];
} else if (arr[j] > r) {
high += arr[j] - r;
}
}
if (sum > r * n || sum < l * n) {
System.out.println(-1);
} else {
System.out.println(Math.max(low, high));
}
}
}
t4
题目:给一个0和1组成的字符串,求子串中有多少“好串”。
对“好串”的定义是:所有的前缀子串中,0的数量全部严格大于1的数量
计算好串的个数
/**
* 找规律
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.next();
int cnt0 = 0;
long sum = 0;
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) == '0') {
cnt0++;
sum += cnt0;
} else {
cnt0--;
if (cnt0 > 0) {
sum += cnt0;
} else {
cnt0 = 0;
}
}
}
System.out.println(sum);
}

海康威视公司福利 1182人发布
