当前位置:   article > 正文

第十届蓝桥杯大赛软件类省赛Java研究生组-题解_蓝桥杯研究生组java真题

蓝桥杯研究生组java真题

目录

试题A:立方和

试题B:子串数字

试题C:质数

试题D:最短路

试题E:RSA解密

试题F:Fibonacci数列与黄金分割

试题G:扫地机器人

试题H:修改数组

试题I:组合数问题

试题J:空间跳跃


试题A:立方和

答案:4097482414389

思路:直接枚举就可以,不过要用long,用int会爆的。

  1. public class Main {
  2. public static void main(String[] args) {
  3. long sum = 0 ;
  4. for(long i=1; i<=2019; i++){
  5. if(f(i)){
  6. long ans = i * i * i ;
  7. sum += ans ;
  8. }
  9. }
  10. System.out.println(sum);
  11. }
  12. private static boolean f(long x){
  13. String s = String.valueOf(x) ;
  14. for(int i=0; i<s.length(); i++){
  15. if(s.charAt(i)=='2' || s.charAt(i)=='0' || s.charAt(i)=='1' || s.charAt(i)=='9'){
  16. return true ;
  17. }
  18. }
  19. return false ;
  20. }
  21. }

试题B:子串数字

答案:3725573269

思路:逻辑题,AC代码如下:

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in) ;
  5. long sum = 0 ;
  6. int num = 0 ;
  7. String s = input.next() ;
  8. for(int i=0; i<s.length(); i++){
  9. num = s.charAt(s.length()-i-1) -'A' + 1 ;
  10. sum += num * Math.pow(26,i) ;
  11. }
  12. System.out.println(sum);
  13. }
  14. }

 

试题C:质数

答案:17569

 思路:枚举1~2019,写个方法判断是否是质数就可以了。

  1. public class Main {
  2. public static void main(String[] args) {
  3. int ans=0, cnt = 0 ;
  4. for(int i=2; cnt!=2019; i++){
  5. if(f(i)){
  6. cnt ++ ;
  7. ans = i ;
  8. }
  9. }
  10. System.out.println(ans);
  11. }
  12. private static boolean f(int x){
  13. for(int i=2; i<x; i++){
  14. if(x%i==0){
  15. return false ;
  16. }
  17. }
  18. return true ;
  19. }
  20. }

试题D:最短路

答案:6

 思路:这题不需要写代码,我没看错的话是6,这题和最短路算法没毛线关系,倒是可以区分红绿色盲。

试题E:RSA解密

答案:579706994112328949

 

思路:扩展欧几里得原理+快速幂+快速乘

这题要求数论要好,这题我参考的别人的代码,如下所示:

  1. public class Main {
  2. static long p, q, m, x, y;
  3. static long n = 1001733993063167141L;
  4. public static void main(String[] args) {
  5. long d = 212353L;
  6. long c = 20190324L;
  7. p = 2;
  8. // 先求p、q
  9. while (true) {
  10. if ((n / p) * p == n) {
  11. q = n / p;
  12. break;
  13. }
  14. p++;
  15. }
  16. // 再求e
  17. m = (p - 1) * (q - 1);
  18. // ans[1] == x ans[2] = y
  19. long[] ans = exgcd(d, m);
  20. ans[1] = (ans[1] + m) % m; // 579706994112328949
  21. // X = C^e % n
  22. System.out.println(qpow(c, ans[1]));
  23. }
  24. public static long[] exgcd(long a, long b) {
  25. long ans;
  26. long[] result = new long[3];
  27. if (b == 0) {
  28. result[0] = a;
  29. // 这里的result[1]、result[2]分别相当于一个解中的x、y
  30. result[1] = 1;
  31. result[2] = 0;
  32. return result;
  33. }
  34. // temp数组中存储的是上一组的解,temp[1]相当于X2,temp[2]相当于Y2
  35. long[] temp = exgcd(b, a % b);
  36. // result[0]存储的就是两个数的最大公约数
  37. ans = temp[0];
  38. result[0] = ans;
  39. // 这里result[1]相当于X1,result[2]相当于Y1
  40. result[1] = temp[2];
  41. result[2] = temp[1] - (a / b) * temp[2];
  42. return result;
  43. }
  44. public static long qpow(long a, long b) {
  45. // 累乘就初始为1
  46. long ans = 1;
  47. while (b > 0) {
  48. if (b % 2 == 1)
  49. ans = qmul(ans, a);
  50. a = qmul(a, a);
  51. b /= 2;
  52. }
  53. return ans;
  54. }
  55. public static long qmul(long a, long b) {
  56. // 累加就初始为0
  57. long ans = 0;
  58. while (b > 0) {
  59. if (b % 2 == 1) {
  60. ans += a;
  61. ans %= n;
  62. }
  63. a *= 2;
  64. a %= n;
  65. b /= 2;
  66. }
  67. return ans;
  68. }
  69. }

试题F:Fibonacci数列与黄金分割

思路:N到达20就比值就恒定了,20之前调用函数计算,20之后直接打印输出。 

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in) ;
  5. int N = input.nextInt() ;
  6. if(N<=20) {
  7. System.out.printf("%.8f", 1.0 * f(N) / f(N + 1));
  8. }else{
  9. System.out.println(0.61803399);
  10. }
  11. }
  12. private static double f(int n){
  13. if(n==1 || n==2){
  14. return 1 ;
  15. }
  16. return f(n-1) + f(n-2) ;
  17. }
  18. }

试题G:扫地机器人

思路: 这题最初没想到,参考别人的思路,二分+贪心的思想。

二分机器人的扫地范围,当每个机器人清扫的面积相差很小时,耗时较少,
* 假设二分的扫地范围是x,对于每一个扫地机器人,我们尽可能让它扫地的右边界大一些,
* 也就是扫过的格子,没有必要绝对不扫。最后看扫地的右边界是否大于等于格子的边界,
* 如果是的话,就说明符合条件,否则就不符合条件。

  1. import java.util.Arrays;
  2. import java.util.Scanner;
  3. public class Main {
  4. static int N, K ;
  5. static int [] a ;
  6. public static void main(String[] args) {
  7. Scanner input = new Scanner(System.in) ;
  8. N = input.nextInt() ;
  9. K = input.nextInt() ;
  10. a = new int [K+1] ;
  11. for(int i=1; i<=K; i++){
  12. a[i] = input.nextInt() ;
  13. }
  14. Arrays.sort(a) ;
  15. int l = 0, r = N, mid, ans=0 ;
  16. while(l<=r){
  17. mid = (l+r)>>1 ;
  18. if(check(mid)){
  19. r = mid - 1 ;
  20. ans = mid ;
  21. }else{
  22. l = mid + 1 ;
  23. }
  24. }
  25. System.out.println((ans-1)*2);
  26. }
  27. private static boolean check(int x){
  28. int sum = 0 ;
  29. for(int i=1; i<=K; i++){
  30. if(a[i]-x<=sum)
  31. {
  32. if(a[i]<=sum) sum=a[i]+x-1;
  33. else sum=sum+x;
  34. }
  35. else return false;
  36. }
  37. return sum >= N;
  38. }
  39. }

试题H:修改数组

思路1:第一想法,开辟一个标记数组flag,去标记之前出现过,从前向后遍历,遇到出现过的就加1再判断,这种方法简单快捷,不过对于最后20%的测试数据可能超时。

 

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in) ;
  5. int N = input.nextInt() ;
  6. int [] a = new int [N] ;
  7. boolean [] flag = new boolean [1000001] ;
  8. for(int i=0; i<N; i++){
  9. a[i] = input.nextInt() ;
  10. }
  11. for(int i=0; i<N; i++){
  12. if(!flag[a[i]]){
  13. flag[a[i]] = true ;
  14. }else{
  15. int num = a[i] + 1 ;
  16. while(flag[num]){
  17. num ++ ;
  18. }
  19. a[i] = num ;
  20. flag[num] = true ;
  21. }
  22. }
  23. for(int ans : a){
  24. System.out.print(ans + " ");
  25. }
  26. }
  27. }

思路2:标准解法,并查集,乍一下没想到这题竟然考的并查集。如果出现过,就将该数字加1作为该数字的爹,下次直接找它爹就行,不要再找它,就不重复了。

  1. import java.util.Scanner;
  2. public class Main {
  3. static int N;
  4. static int [] A ;
  5. static int [] parent ;
  6. public static void main(String[] args) {
  7. Scanner input = new Scanner(System.in) ;
  8. N = input.nextInt() ;
  9. A = new int [N] ;
  10. parent = new int [1000001] ;
  11. for(int i=1; i<parent.length; i++){
  12. parent[i] = i ;
  13. }
  14. for(int i=0; i<N; i++){
  15. A[i] = input.nextInt() ;
  16. }
  17. for(int i=0; i<A.length; i++){
  18. int k = find(A[i]) ;
  19. A[i] = k ; //将它爹赋值给它
  20. parent[A[i]] = find(parent[A[i]+1]) ; //更新爹
  21. }
  22. for(int ans : A){
  23. System.out.print(ans + " ");
  24. }
  25. }
  26. private static int find(int x){
  27. if(x!=parent[x]){
  28. parent[x] = find(parent[x]) ;
  29. }
  30. return parent[x] ;
  31. }
  32. }

试题I:组合数问题

思路:拿分为主,面向测试用例编程,直接组合数递推公式暴力求解,可以通过40%的测试用例。

满分解法是数位dp,卢卡斯定理!!!

  1. import java.util.Scanner;
  2. public class Main {
  3. static int mod = 1000000007 ;
  4. static int [][] c ;
  5. public static void main(String[] args) {
  6. Scanner input = new Scanner(System.in) ;
  7. int t = input.nextInt() ;
  8. int k = input.nextInt() ;
  9. c = new int [2001][2001] ;
  10. init();
  11. for(int i=0; i<t; i++){
  12. int ans = 0 ;
  13. int n = input.nextInt() ;
  14. int m = input.nextInt() ;
  15. for(int j=1; j<=n; j++){
  16. for(int l=0; l<=Math.min(j,m); l++){
  17. if(c[j][l]%k==0){
  18. ans = (ans + 1) % mod ;
  19. }
  20. }
  21. }
  22. System.out.println(ans%mod);
  23. }
  24. }
  25. private static void init(){
  26. for(int i=0; i<=2000; i++){
  27. for(int j=0; j<=i; j++){
  28. if(j==0){
  29. c[i][j] = 1 ;
  30. }else{
  31. c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod ;
  32. }
  33. }
  34. }
  35. }
  36. }

试题J:空间跳跃

这题没思路,题解参考链接:https://www.icode9.com/content-1-628488.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/342391?site
推荐阅读
相关标签
  

闽ICP备14008679号