第十一届蓝桥杯大赛软件类省赛Java研究生组-题解
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十一届蓝桥杯大赛软件类省赛Java研究生组-题解相关的知识,希望对你有一定的参考价值。
目录
试题A :约数个数
答案:96
思路:简单枚举,注意1和本身也算约数。
public class Main
public static void main(String[] args)
int ans = 0 ;
for(int i=1; i<=78120; i++)
if(78120%i==0)
ans ++ ;
System.out.println(ans);
试题B:跑步锻炼
答案:8879
思路:Java日期时间API的应用,根据平年和闰年,算出总天数days,算出周一的天数a,算出初一的天数b,再算出既是初一又是周一的天数ans,那么最终的跑步路程为(days-(a+b-ans)) + (a+b-ans)*2。
import java.util.Calendar;
import static java.time.Year.isLeap;
public class Main
public static void main(String[] args)
Calendar c = Calendar.getInstance() ;
int years = 2000;
int same = 0 ;
//Calendar的月份是从0到11的,不是1到12,需要注意,谨慎一点,时间API也是常考的
c.set(years,0, 1) ;
while(c.get(Calendar.YEAR) != 2020 || c.get(Calendar.MONTH) != 9 || c.get(Calendar.DATE) != 1)
//从2000年1月1日开始判断,每次判断一个月的第一天,如果是周一,就用same记录
int weekday = c.get(Calendar.DAY_OF_WEEK) - 1 ;
if(weekday==1)
same ++ ;
if(c.get(Calendar.MONTH)<11)
c.set(Calendar.MONTH, c.get(Calendar.MONTH)+1) ;
else
years ++ ;
c.set(Calendar.YEAR, years);
c.set(Calendar.MONTH, 0);
long days = 0 ;
for(int year=2000; year<=2020; year++)
if(isLeap(year))
days += 366 ;
else
days += 365 ;
days = days - 31 - 30 - 30 ;
long a = (days-6) / 7 + 1; //星期1
long b = 12*20 + 10 ; //初一
long ans = days - (a+b-same) ;
System.out.println(2*(a+b-same)+ans);
试题C:平面分割
答案:1391
思路:没有思路,哈哈,我看别人的思路是让尽可能的相交,这样产生的区域就越多,至于具体怎么推导的,可以看下这个。参考链接:蓝桥杯试题E: 平面分割 - riz9 - 博客园
试题D:蛇形填数
答案:761
思路:模拟斜对角向上和向下填数过程即可。
//试题D-蛇形填数
public class Main
public static void main(String[] args)
int row = 0, col = 0 ;
int num = 0 ;
while(true)
num ++ ;
if(row==19 && col ==19)
break ;
if((row+col)%2==0) //向上走
if(row==0)
col ++ ;
else
row -- ;
col ++ ;
else //向下走
if(col==0)
row ++ ;
else
row ++ ;
col -- ;
System.out.println(num);
试题E:排序
答案:jonmlkihgfedcba
相邻交换100次,最短需要15个字符,正常前15个字符逆序,交换1+2+3+...+14=105次,故把j放到首位,交换100次,最短并且字典序最小。
public class Main
public static void main(String[] args)
int ans = 0 ;
//前15个小写字母逆序,执行105交换,此时是最短的,要保证字典序最小,把第5个移动到首位
System.out.println("jonmlkihgfedcba");
试题F:成绩统计
思路:枚举,计算即可,注意四舍五入。
import java.util.Scanner;
public class Main
public static void main(String[] args)
Scanner input = new Scanner(System.in) ;
int n =input.nextInt() ;
int pass = 0, excellent = 0 ;
for(int i=0; i<n; i++)
int grade = input.nextInt() ;
if(grade>=85)
excellent ++ ;
if(grade>=60)
pass++ ;
int ans1, ans2 ;
double x = 1.0 * pass / n * 1000;
double y = 1.0 * excellent / n * 1000 ;
if(x==1000)
System.out.println(100 + "%");
else
String s1 = String.valueOf(x);
int c1 = s1.charAt(2) - '0';
if (c1 >= 5)
ans1 = Integer.parseInt(s1.substring(0, 2)) + 1;
else
ans1 = Integer.parseInt(s1.substring(0, 2));
System.out.println(ans1 + "%");
if(y==1000)
System.out.println(100 + "%");
else
String s2 = String.valueOf(y);
int c2 = s2.charAt(2) - '0';
if (c2 >= 5)
ans2 = Integer.parseInt(s2.substring(0, 2)) + 1;
else
ans2 = Integer.parseInt(s2.substring(0, 2));
System.out.println(ans2 + "%");
试题G:回文日期
思路:枚举N+1天开始的所有日期,判断是否满足条件即可。细节很多,需要注意处理细节。
import java.util.Scanner;
import static java.time.Year.isLeap ;
public class Main
public static void main(String[] args)
Scanner input = new Scanner(System.in) ;
int N = input.nextInt() ;
for(int i=N+1;i<=99991231;i++)
int d = i % 100 ;
if(d>31)
i += 68 ;
if(i%10000>=13000)
i += i / 10000 + 999 ;
if(f1(i))
System.out.println(i);
break ;
for(int i=N+1;i<=99991231; i++)
int d = i % 100 ;
if(d>31)
i += 68 ;
if(i%10000>=13000)
i += i / 10000 + 999;
if(f1(i) && f2(i))
System.out.println(i);
break ;
public static boolean f1(int i)
String s = String.valueOf(i) ;
int month = Integer.parseInt(s.substring(4,6)) ;
int day = Integer.parseInt(s.substring(6,8)) ;
if(month==0 || day==0)
return false ;
if(month>12 || day>31)
return false ;
if(month==4 || month==6 || month==9 || month==11 )
if(day>30)
return false ;
if(isLeap(Integer.parseInt(s.substring(0,4))))
if(day>29)
return false ;
else
if(day>28)
return false ;
if(!isPalindrome(s))
return false ;
return true ;
private static boolean isPalindrome(String s)
for(int i=0; i<s.length(); i++)
if(s.charAt(i) != s.charAt(s.length()-1-i))
return false ;
return true ;
public static boolean f2(int i)
String s = String.valueOf(i) ;
if(s.charAt(0)==s.charAt(2) && s.charAt(2) == s.charAt(5) && s.charAt(7)==s.charAt(5))
if(s.charAt(1)==s.charAt(3) && s.charAt(3) == s.charAt(4) && s.charAt(4)==s.charAt(6))
if(s.charAt(0) != s.charAt(1))
return true ;
return false ;
试题H:作物杂交
思路:记忆化搜索,ans数组记忆已经得到的结果,vis数组标记当前作物是否已经生成,如果目标种子没有合成,遍历当前所有已有的杂交组合,对于合成值等于target的,递归计算两个合成target值得种子分别合成所需要得最大值。求出所有可能得最小值即是答案。AC代码如下:
import java.util.Scanner;
public class Main
static int N, M, K, T ;
static int [][] hby ;
static int [] time ;
static int [] seed ;
static int [] maxTime ;
static int [] vis ;
static int [] ans ;
public static void main(String[] args)
Scanner input = new Scanner(System.in) ;
N = input.nextInt() ;
M = input.nextInt() ;
K = input.nextInt() ;
T = input.nextInt() ;
time = new int [N+1] ;
seed = new int [M] ;
hby = new int [K][3] ;
maxTime = new int [K] ; //记录两两杂交的最大时间
vis = new int [N+1] ;
ans = new int [N+1] ;
for(int i=1; i<=N; i++)
time[i] = input.nextInt() ;
for(int i=0; i<M; i++)
seed[i] = input.nextInt() ;
vis[seed[i]] = 1 ; //记录作物已经合成
for(int i=0; i<K; i++)
hby[i][0] = input.nextInt() ;
hby[i][1] = input.nextInt() ;
hby[i][2] = input.nextInt() ;
maxTime[i] = Math.max(time[hby[i][0]], time[hby[i][1]]) ;
System.out.println(dfs(T));
private static int dfs(int target)
if(vis[target]!=1)
int min = Integer.MAX_VALUE ;
for(int i=0; i<K; i++)
if(hby[i][2]==target)
min = Math.min(min, maxTime[i] + Math.max(dfs(hby[i][0]), dfs(hby[i][1]))) ;
vis[target] = 1 ;
ans[target] = min ;
return min ;
else
return ans[target] ;
试题I:子串分值
思路1:枚举+HashMap记录,枚举所有可能,Map记录每个出现1次的字符,统计个数。可以通过部分测试用例,拿到10分+没问题。
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main
public static void main(String[] args)
Scanner input = new Scanner(System.in) ;
String s = input.next() ;
long ans = 0 ;
for(int i=0; i<s.length(); i++)
for(int j=i+1; j<=s.length(); j++)
ans += f(s.substring(i,j));
System.out.println(ans);
public static long f(String s)
long sum = 0 ;
Map<Character, Integer> map = new HashMap<>() ;
for(int i=0; i<s.length(); i++)
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1) ;
for(char c : map.keySet())
if(map.get(c)==1)
sum ++ ;
return sum ;
思路2:AC代码,动态规划思想,dp[i]表示以i结尾的字符串中的每个字符的贡献值,place数组记录每个字符上一次出现的位置,ans记录当前字符的贡献值,sum为所有字符的贡献值,每一次更新dp[c]和place[c].
import java.util.*;
public class Main1
static int ans, sum ;
static int [] dp ;
static int [] place ;
public static void main(String[] args)
Scanner input = new Scanner(System.in) ;
String s = input.next() ;
dp = new int [26] ; //dp[i]表示以i结尾的字符串中每个字符的贡献值
place = new int [26] ; //记录每个字符出现的位置
Arrays.fill(place, -1) ;
for(int i=0; i<s.length(); i++)
int c = s.charAt(i) - 'a' ;
ans += i - place[c] - dp[c] ;
sum += ans ;
dp[c] = i - place[c] ;
place[c] = i ;
System.out.println(sum);
试题J:装饰珠
参考链接:算法练习题27---蓝桥杯2020省赛“装饰珠”_杨大熊的代码世界的博客-CSDN博客_蓝桥杯 装饰珠
以上是关于第十一届蓝桥杯大赛软件类省赛Java研究生组-题解的主要内容,如果未能解决你的问题,请参考以下文章
第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(python解答)
2020 第十一届蓝桥杯大赛软件赛省赛(第一场),C/C++大学B组题解
2022 第十三届蓝桥杯大赛软件赛省赛,C/C++ 大学B组题解
2022 第十三届蓝桥杯大赛软件赛省赛(第二场),C/C++ 大学B组题解