0


蓝桥杯31天冲刺打卡题解(Day11)

Day11

第一题

第十一届2020年蓝桥杯国赛

天干地支

  1. JavaC组第6
  1. 模拟

一道很复杂,但又不完全复杂的模拟题。

我们可以写一堆

  1. if/else

用循环来判断,但我们其实可以找到其中的规律:在

  1. 2020

年时,是庚子年,我们判断一下

  1. 0000

年是什么年,我们可以发现天干是以

  1. 10

为单位的,利用

  1. 2020 % 10 = 0

发现

  1. 0000

年的天干也是庚,地支是以

  1. 12

为单位的,计算

  1. 2020 % 12 = 4

,所以地支要往前推

  1. 4

年,地支为申,即

  1. 0000

年为庚申年,那么根据模拟法可知:

year % 10 = 0 时,天干为庚

year % 10 = 1 时,天干为庚的下一个 辛

以此类推…

year % 10 = 0 时,地支为申

year % 10 = 1 时,地支为申的下一个 酉

所以我们可以来两个数组存储天干和地支,从

  1. 0000

年开始存储,这样就可以根据

  1. %

的余数来判断当前的年份了。

  1. import java.util.Scanner;publicclassMain{publicstaticvoidmain(String[] args){
  2. Scanner sc =newScanner(System.in);int year = sc.nextInt();
  3. String[] tg ={"geng","xin","ren","gui","jia","yi","bing","ding","wu","ji"};
  4. String[] dz ={"shen","you","xu","hai","zi","chou","yin","mao","chen","si","wu","wei"};
  5. System.out.println(tg[year %10]+ dz[year %12]);}}

第二题

第八届2017年蓝桥杯省赛

包子凑数

  1. JavaB组第8
  1. 完全背包问题

假设我们有

  1. N
  2. N
  3. N 个蒸笼,每个蒸笼的包子分别为
  4. A
  5. 1
  6. ,
  7. A
  8. 2
  9. .
  10. .
  11. .
  12. A
  13. n
  14. A_1,A_2...A_n
  15. A1​,A2​...An​,且他们的最大公约数是
  16. d
  17. d
  18. d,且
  19. d
  20. >
  21. 1
  22. d>1
  23. d>1,所有数都是
  24. d
  25. d
  26. d 的倍数,如果一个数不能被
  27. d
  28. d
  29. d 整数,则说明这个数也一定不能被
  30. A
  31. 1
  32. ,
  33. A
  34. 2
  35. .
  36. .
  37. .
  38. A
  39. n
  40. A_1,A_2...A_n
  41. A1​,A2​...An 凑出来,所以此时会有正无穷
  42. I
  43. N
  44. F
  45. INF
  46. INF 个数凑不出来。

  1. g
  2. c
  3. d
  4. (
  5. A
  6. 1
  7. ,
  8. A
  9. 2
  10. .
  11. .
  12. .
  13. A
  14. n
  15. )
  16. =
  17. 1
  18. gcd(A_1,A_2...A_n)=1
  19. gcd(A1​,A2​...An​)=1 时,不能凑出来的数一定是有限个,这是依据裴蜀定理,裴蜀定理是基于两个数
  20. a
  21. ,
  22. b
  23. a,b
  24. a,b 的定理,当
  25. g
  26. c
  27. d
  28. (
  29. a
  30. ,
  31. b
  32. )
  33. =
  34. 1
  35. gcd(a,b) = 1
  36. gcd(a,b)=1 时,最大不能表示的数是:
  37. (
  38. a
  39. 1
  40. )
  41. (
  42. b
  43. 1
  44. )
  45. 1
  46. (a-1)(b-1)-1
  47. (a1)(b1)−1 当有
  48. N
  49. N
  50. N 个数时定理也同样适用,当数变多时,这个上界必然会更小,因为可选的数变多了,因为
  51. 1
  52. N
  53. 100
  54. 1\leq N \leq 100
  55. 1N100,小于
  56. 100
  57. 100
  58. 100 中最大互质的两个数是
  59. 98
  60. ,
  61. 99
  62. 98,99
  63. 98,99,所以这里的上界我们取到
  64. 10000
  65. 10000
  66. 10000 即可。

此时这个问题就变成了完全背包问题,在

  1. 10000
  2. 10000
  3. 10000 以内有多少个数不能被组合出来。

闫式DP分析法

image-20220319190821350

此时的状态转移方程:

  1. f
  2. (
  3. i
  4. ,
  5. j
  6. )
  7. =
  8. f
  9. (
  10. i
  11. 1
  12. ,
  13. j
  14. )
  15. f
  16. (
  17. i
  18. 1
  19. ,
  20. j
  21. A
  22. i
  23. )
  24. f
  25. (
  26. i
  27. 1
  28. ,
  29. j
  30. 2
  31. A
  32. i
  33. )
  34. .
  35. .
  36. .
  37. f
  38. (
  39. i
  40. 1
  41. ,
  42. j
  43. 0
  44. )
  45. f(i,j)=f(i-1,j)|f(i-1,j-A_i)|f(i-1,j-2A_i)|...|f(i-1,j\leq0)
  46. f(i,j)=f(i1,j)∣f(i1,jAi​)∣f(i1,j2Ai​)∣...∣f(i1,j0)

时间复杂度为

  1. O
  2. (
  3. N
  4. 3
  5. )
  6. O(N^3)
  7. O(N3),状态的数量是
  8. N
  9. 2
  10. N^2
  11. N2 个,转移的数量是
  12. N
  13. N
  14. N 个,显然是需要优化一下的,一般的背包问题时间复杂度是
  15. O
  16. (
  17. N
  18. 2
  19. )
  20. O(N^2)
  21. O(N2)。

我们做一下

  1. j
  2. j
  3. j 的变量变换:
  4. f
  5. (
  6. i
  7. ,
  8. j
  9. A
  10. i
  11. )
  12. =
  13. f
  14. (
  15. i
  16. 1
  17. ,
  18. j
  19. A
  20. i
  21. )
  22. f
  23. (
  24. i
  25. 1
  26. ,
  27. j
  28. 2
  29. A
  30. i
  31. )
  32. f
  33. (
  34. i
  35. 1
  36. ,
  37. j
  38. 3
  39. A
  40. i
  41. )
  42. .
  43. .
  44. .
  45. f(i,j-A_i)=f(i-1,j-A_i)|f(i-1,j-2A_i)|f(i-1,j-3A_i)|...
  46. f(i,jAi​)=f(i1,jAi​)∣f(i1,j2Ai​)∣f(i1,j3Ai​)∣...

此时这个等式可以替换为第一个等式从第二项开始后面的所有项:

image-20220318224727280

状态转移方程优化为:

  1. f
  2. (
  3. i
  4. ,
  5. j
  6. )
  7. =
  8. f
  9. (
  10. i
  11. 1
  12. ,
  13. j
  14. )
  15. f
  16. (
  17. i
  18. ,
  19. j
  20. A
  21. i
  22. )
  23. f(i,j)=f(i-1,j)|f(i,j-A_i)
  24. f(i,j)=f(i1,j)∣f(i,jAi​)
  1. import java.util.Scanner;publicclassMain{staticfinalint N =110, M =10010;staticint[] a =newint[N];staticboolean[][] f =newboolean[N][M];publicstaticvoidmain(String[] args){
  2. Scanner sc =newScanner(System.in);int n = sc.nextInt();int d =0;for(int i =1; i <= n; i++){
  3. a[i]= sc.nextInt();
  4. d =gcd(d, a[i]);}if(d !=1) System.out.println("INF");// 最大公约数不为1 有无限多个数凑不出来else{
  5. f[0][0]=true;// 0件物品 体积为0时也是一种方案for(int i =1; i <= n; i++){for(int j =0; j < M; j++){
  6. f[i][j]= f[i -1][j];// 第一项一定存在if(j >= a[i]) f[i][j]|= f[i][j - a[i]];// 第二项不一定存在 用或"|"}}int res =0;for(int i =0; i < M; i++){if(!f[n][i]) res++;}
  7. System.out.println(res);}}privatestaticintgcd(int a,int b){return b !=0?gcd(b, a % b): a;}}

我们发现我们的方程第

  1. i
  2. i
  3. i 维只依赖于第
  4. i
  5. i
  6. i
  7. i
  8. 1
  9. i-1
  10. i1 项,所以我们可以将数组优化成一维:
  1. import java.util.Scanner;publicclassMain{staticfinalint N =110, M =10010;staticint[] a =newint[N];staticboolean[] f =newboolean[M];publicstaticvoidmain(String[] args){
  2. Scanner sc =newScanner(System.in);int n = sc.nextInt();int d =0;for(int i =1; i <= n; i++){
  3. a[i]= sc.nextInt();
  4. d =gcd(d, a[i]);}if(d !=1) System.out.println("INF");// 最大公约数不为1 有无限多个数凑不出来else{
  5. f[0]=true;// 0件物品 体积为0时也是一种方案for(int i =1; i <= n; i++){for(int j = a[i]; j < M; j++){
  6. f[j]|= f[j - a[i]];}}int res =0;for(int i =0; i < M; i++){if(!f[i]) res++;}
  7. System.out.println(res);}}privatestaticintgcd(int a,int b){return b !=0?gcd(b, a % b): a;}}

第三题

第十届2019年蓝桥杯国赛

求值

  1. C++B组第4
  1. 填空题

目的是找到一个最小数,且它的约数个数是100。

简单的暴力打表题,我们在编译器上跑,在oj上提交结果的代码即可。

  1. publicclassMain{publicstaticvoidmain(String[] args){for(int i =1;; i++){if(cnt(i)==100){// 有100个约数的最小数
  2. System.out.println(i);break;}}}// 求约数privatestaticintcnt(int a){int ans =0;for(int i =1; i <= a; i++)if(a % i ==0) ans++;return ans;}}

提交代码:

  1. publicclassMain{publicstaticvoidmain(String[] args){
  2. System.out.println(45360);}}

第四题

第八届2017年蓝桥杯省赛

青蛙跳杯子

  1. JavaC组第9
  1. bfs
  1. import java.util.HashMap;
  2. import java.util.LinkedList;
  3. import java.util.Queue;
  4. import java.util.Scanner;
  5. public class Main {
  6. static int l;
  7. static int[] dx = {1, -1, 2, -2, 3, -3};
  8. static String a = "";
  9. static String b = "";
  10. public static void main(String[] args){
  11. Scanner in = new Scanner(System.in);
  12. a = in.next();
  13. b = in.next();
  14. l = a.length();
  15. System.out.println(bfs());
  16. }
  17. private static int bfs() {
  18. Queue<String> q = new LinkedList<>();
  19. q.offer(a);
  20. HashMap<String, Integer> dist = new HashMap<>();
  21. dist.put(a, 0);
  22. while (!q.isEmpty()) {
  23. StringBuilder t = new StringBuilder(q.poll());
  24. int dis = dist.get(t.toString());
  25. if (t.toString().equals(b)) {
  26. return dis;
  27. }
  28. int pos = t.indexOf("*");
  29. for (int i = 0; i < 6; i ++) {
  30. int nx = pos + dx[i];
  31. if (nx >= 0 && nx < l) {
  32. char x = t.toString().charAt(pos);
  33. char y = t.toString().charAt(nx);
  34. t.setCharAt(pos, y);
  35. t.setCharAt(nx, x);
  36. if (!dist.containsKey(t.toString())) {
  37. dist.put(t.toString(), dis + 1);
  38. q.offer(t.toString());
  39. }
  40. x = t.toString().charAt(pos);
  41. y = t.toString().charAt(nx);
  42. t.setCharAt(pos, y);
  43. t.setCharAt(nx, x);
  44. }
  45. }
  46. }
  47. return -1;
  48. }
  49. }
标签: 蓝桥杯 java 算法

本文转载自: https://blog.csdn.net/weixin_53407527/article/details/123587033
版权归原作者 小成同学_ 所有, 如有侵权,请联系我们删除。

“蓝桥杯31天冲刺打卡题解(Day11)”的评论:

还没有评论