一. 编程题

1. 第一题 50%

题目:环形数组,长为 n,数组每个位置的值表示大小,一个字符串只包含 ‘R’、’P’ 两种字符,代表数组对应位置为红色 or 紫色。小红和小紫都从数组起点开始一起走,每次走一格,走到红色格子则小红的分数加上对应格子的数值,走到紫色格子则小紫的分数加上对应格子的数值。求问走了 x 步后,小红和小紫的分数。

  • 直接做只过了 50% ```cpp

    include

    include

    include

    using namespace std;

int main() { int n; cin >> n; vector nums(n); for(int i = 0; i < n; ++i) cin >> nums[i]; string colors; cin >> colors; long long allVal1 = 0; long long allVal2 = 0; for(int i = 0; i < n; ++i) { if(colors[i] == ‘R’) allVal1 += nums[i]; else if(colors[i] == ‘P’) allVal2 += nums[i]; }

  1. int Q; // 询问次数
  2. cin >> Q;
  3. for(int q = 0; q < Q; ++q)
  4. {
  5. int x; // 第 x 天后
  6. cin >> x;
  7. int completeDays = x / n;
  8. int remainDays = x % n;
  9. long long val1 = completeDays * allVal1;
  10. long long val2 = completeDays * allVal2;
  11. for(int i = 0; i < remainDays; ++i)
  12. {
  13. if(colors[i] == 'R')
  14. val1 += nums[i];
  15. else if(colors[i] == 'P')
  16. val2 += nums[i];
  17. }
  18. cout << val1 << " " << val2 << endl;
  19. }
  20. return 0;

}

  1. - 优化:前缀和、q/nq%n 之类的优化
  2. <a name="rQG5u"></a>
  3. ## 2. 第二题 95%
  4. 两人沿三角形边界匀速跑,小红从顶点 A 开始跑,小明从顶点 B 开始走。给定三角形顶点 ABC 的坐标,以及小红的速度 v1,小红的方向 d1,小明的速度 v2,小明的速度 d2,问两人第一次相遇的时间,如果不能相遇则输出 -1。(方向为 0 代表:A->B->C->A,方向为 1 代表:A->C->B->A
  5. - 下面的代码过了 95%,应该是忘了一圈内追不上取余之类的操作
  6. - 没有考虑两人反向(不是相向),但速度都为 0 case
  7. ```cpp
  8. #include <iostream>
  9. #include <vector>
  10. #include <algorithm>
  11. #include <math.h>
  12. using namespace std;
  13. int main()
  14. {
  15. int xa, ya, xb, yb, xc, yc;
  16. cin >> xa >> ya >> xb >> yb >> xc >> yc;
  17. // vector<int> posArr(6);
  18. // for(int i = 0; i < 6; ++i)
  19. // cin >> posArr[i];
  20. int v1, d1, v2, d2;
  21. cin >> v1 >> d1 >> v2 >> d2;
  22. double t = 0.0;
  23. double lenAB = sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya- yb));
  24. double lenBC = sqrt((xb - xc) * (xb - xc) + (yb - yc) * (yb- yc));
  25. double lenAC = sqrt((xa - xc) * (xa - xc) + (ya - yc) * (ya- yc));
  26. double lenAll = lenAB + lenBC + lenAC;
  27. // cout << lenAB << ", " << lenBC << ", " << lenAC << endl;
  28. if(d1 == 0 && d2 == 1)
  29. t = lenAB / (v1 + v2);
  30. else if(d1 == 1 && d2 == 0)
  31. t = (lenAC + lenBC) / (v1 +v2);
  32. else if(v1 == v2)
  33. t = -1;
  34. else
  35. {
  36. if(d1 == 0 && d2 == 0)
  37. {
  38. if(v1 > v2)
  39. t = lenAB / (v1 - v2);
  40. else
  41. t = (lenBC + lenAC) / (v2 - v1);
  42. }
  43. else if(d1 == 1 && d2 == 1)
  44. {
  45. if(v2 > v1)
  46. t = lenAB / (v2 - v1);
  47. else
  48. t = (lenBC + lenAC) / (v1 - v2);
  49. }
  50. }
  51. cout << t << endl;
  52. return 0;
  53. }

3. 第三题 88.24%

题目:长为 n 的数组,存储的元素代表数值,长为 n 的字符串代表数组对应位置的颜色(只包含红 R、蓝 B 两种颜色),要求最短的连续区间长度,要满足:区间内红色格子的积 x、区间内蓝色格子的积 y,x 末尾 0 的数量 + y 末尾 0 的数量要大于等于给定的 k

思路:只过了 88.24%

  • 滑动窗口
  • 末尾 0 的个数,取决于所有乘数的因子中 2 的个数、5 的个数的最小值(参考:[中等] 172. 阶乘后的零) ```cpp

    include

    include

    include

    include

    using namespace std;

int calCnt5(int num) { int div = 5; int result = 0; while(div <= num) { if(num % div == 0) { ++result; div *= 5; } else break; } return result; }

int calCnt2(int num) { int div = 2; int result = 0; while(div <= num) { if(num % div == 0) { ++result; div *= 2; } else break; } return result; }

int main() { int n, k; cin >> n >> k; vector nums(n); for(int i = 0; i < n; ++i) cin >> nums[i]; string colors; cin >> colors;

  1. int left = 0;
  2. int right = 0;
  3. int red2 = 0;
  4. int red5 = 0;
  5. int blue2 = 0;
  6. int blue5 = 0;
  7. int result = n;
  8. while(right < n)
  9. {
  10. int num = nums[right];
  11. ++right;
  12. int cnt5 = calCnt5(num);
  13. if(colors[right - 1] == 'R')
  14. red5 = red5 + cnt5;
  15. else if(colors[right - 1] == 'B')
  16. blue5 = blue5 + cnt5;
  17. int cnt2 = calCnt2(num);
  18. if(colors[right - 1] == 'R')
  19. red2 = red2 + cnt2;
  20. else if(colors[right - 1] == 'B')
  21. blue2 = blue2 + cnt2;
  22. while(min(red2 + red5) + min(blue2 + blue5) >= k)
  23. {
  24. result = min(result, right - left);
  25. int deleteNum = nums[left];
  26. ++left;
  27. int dCnt5 = calCnt5(deleteNum);
  28. if(colors[left - 1] == 'R')
  29. red5 = red5 - dCnt5;
  30. else if(colors[left - 1] == 'B')
  31. blue5 = blue5 - dCnt5;
  32. int dCnt2 = calCnt2(deleteNum);
  33. if(colors[left - 1] == 'R')
  34. red2 = red2 - dCnt2;
  35. else if(colors[left - 1] == 'B')
  36. blue2 = blue2 - dCnt2;
  37. }
  38. }
  39. cout << result << endl;
  40. return 0;

}

  1. <a name="CLl4Q"></a>
  2. ## 4. 第四题 0%
  3. n 行 m 列的矩阵,存的都是正整数,输入 Q 个 target:
  4. - 对于每个 target,如果数组中的元素 = target,则标为红色(若之前已被标记过则仍为红色),求红色连通块的数量。连通块指的是上、下、左、右有一格相邻
  5. 解法:dfs,示例是对的,但是提交就只能过 0%。。。
  6. ```cpp
  7. #include <iostream>
  8. #include <vector>
  9. using namespace std;
  10. void dfs(vector<vector<int>>& matrix, int row, int col, int target)
  11. {
  12. int n = matrix.size();
  13. int m = matrix[0].size();
  14. if(row < 0 || row >= n || col < 0 || col >= m || matrix[row][col] != target)
  15. return;
  16. matrix[row][col] = -1;
  17. dfs(matrix, row - 1, col, target);
  18. dfs(matrix, row + 1, col, target);
  19. dfs(matrix, row, col - 1, target);
  20. dfs(matrix, row, col + 1, target);
  21. // matrix[row][col] = target;
  22. }
  23. int main()
  24. {
  25. int n, m;
  26. cin >> n >> m;
  27. vector<vector<int>> matrix(n, vector<int>(m));
  28. for(int i = 0; i < n; ++i)
  29. {
  30. for(int j = 0; j < m; ++j)
  31. cin >> matrix[i][j];
  32. }
  33. int Q;
  34. cin >> Q;
  35. for(int q = 0; q < Q; ++q)
  36. {
  37. int target;
  38. cin >> target;
  39. // cout << "target = " << target << endl;
  40. // vector<vector<int>> temp(n, vector<int>(m));
  41. // for(int i = 0; i < n; ++i)
  42. // {
  43. // for(int j = 0; j < m; ++j)
  44. // temp[i][j] = matrix[i][j];
  45. // }
  46. int result = 0;
  47. for(int i = 0; i < n; ++i)
  48. {
  49. for(int j = 0; j < m; ++j)
  50. {
  51. if(matrix[i][j] == target)
  52. {
  53. ++result;
  54. dfs(matrix, i, j, target);
  55. // cout << "i = " << i << ", j = " << j << ", matrix[i][j] = " << temp[i][j] << endl;
  56. }
  57. }
  58. }
  59. cout << result;
  60. if(q != Q - 1)
  61. cout << " ";
  62. }
  63. cout << endl;
  64. return 0;
  65. }
  • 看到有人说用:并查集+map记录同一个数的所有位置

二. 问答题

实现垃圾邮件过滤器:1 百万条的数据集,5 万条是垃圾邮件,95 万条是正常邮件。写下数据处理、特征、模型构建等思路