总结:
2016:凑算法 全排列、递归、数学思维、注意细节(除法小小数问题)
2017:承压计算 找规律、注意细节(最边缘重量计算、除法运算要用double类型存数据)、精确度
2018:复数幂 数学思维、找规律
2019:数列求值 找规律、思维分析
2020-1:合并检测 数学思维(均值不等式)
2020-2:蛇形填数 找规律
2021:直线 数学思维、递归
2022:字符统计 ascll码与字符间转换、思维分析
综上:
蓝桥第3题也会存在一些大数据或者找规律的题型,但总体更偏向数学思维分析,通过数学思维分析题目,找出突破点会使解题轻松很多。并且对代码细节上的要求也更高了。
主要考察:
递归、全排列。
注意全排列时重复情况,如果题目要求不能重复,结果就需要去重。
(如:2016、2021)
数学分析
公式转换、精确度、复数运算、大数求和低位不受高位影响、均值不等式、平面几何思维
(如:2016、2017、2018、2019、2020-1、2021)
找规律
认真读题、抠字眼。注意给出的示例也很重要,认真看。
(如:2017、2018、2019、2020-2)
字符串
字符与数字之间的转换
(如:2022年)
细节
数据精确度、除法造成精度不准的时候将除法转换为乘法
(如:2016、2017)
接下来列出2016-2022年间第三题的详细讲解
2016年
B DEF
A + --- + ------- = 10
C GHI
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
static int[] a={1,2,3,4,5,6,7,8,9};
static int count=0;
public static void main(String[] args){
f(0);
System.out.println(count);
}
public static void f(int k){
if(k>=9){
int A=a[0];
int B=a[1];
int C=a[2];
int D=a[3]*100+a[4]*10+a[5];
int E=a[6]*100+a[7]*10+a[8];
if(B*E + C*D == (10 - A) * C * E)count++;
}
for(int i=k;i<9;i++)//全排列
{
swap(i,k);
f(k+1);
swap(i,k);
}
}
public static void swap(int i,int k){
int t=a[i];
a[i]=a[k];
a[k]=t;
}
答案:29
思路:递归全排列出所有可能的情况的同时,对每种情况判断分析,符合要求则计数。
注意:这道题目的公式中存在除法,存在除法就会有结果为小数,有小数就会存在误差。
所以,为了避免误差需要将除法公式转换为只有乘法的公式再进行计算。
详解请移步:凑算法
2017年
X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。每块金属原料的外形、尺寸完全一致,但重量不同。金属材料被严格地堆放成金字塔形。
7
5 8
7 8 8
9 2 7 2
8 1 4 9 1
8 1 8 8 4 1
7 9 6 1 4 5 4
5 6 5 5 6 9 5 6
5 5 4 7 9 3 5 5 1
7 5 7 9 7 4 7 3 3 1
4 6 4 5 5 8 8 3 2 4 3
1 1 3 3 1 6 6 5 5 4 4 2
9 9 9 2 1 9 1 9 2 9 5 7 9
4 3 3 7 7 9 3 6 1 3 8 8 3 7
3 6 8 1 5 3 9 5 8 3 8 1 8 3 3
8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9
8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4
2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9
7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6
9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3
5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9
6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4
2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4
7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6
1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3
2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8
7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9
7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6
5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
其中的数字代表金属块的重量(计量单位较大)。最下一层的X代表30台极高精度的电子秤。
假设每块原料的重量都十分精确地平均落在下方的两个金属块上,最后,所有的金属块的重量都严格精确地平分落在最底层的电子秤上。电子秤的计量单位很小,所以显示的数字很大。工作人员发现,其中读数最小的电子秤的示数为:2086458231。请你推算出:读数最大的电子秤的示数为多少?
注意:需要提交的是一个整数,不要填写任何多余的内容。
public static void main(String[] args){
double[][] a={
{7},
{5, 8},
{7, 8, 8},
{9, 2, 7, 2},
{8, 1, 4, 9, 1},
{8, 1, 8, 8, 4, 1},
{7, 9, 6, 1, 4, 5, 4},
{5, 6, 5, 5, 6, 9, 5, 6},
{5, 5, 4, 7, 9, 3, 5, 5, 1},
{7, 5, 7, 9, 7, 4, 7, 3, 3, 1},
{4, 6, 4, 5, 5, 8, 8, 3, 2, 4, 3},
{1, 1, 3, 3, 1, 6, 6, 5, 5, 4, 4, 2},
{9, 9, 9, 2, 1, 9, 1, 9, 2, 9, 5, 7, 9},
{4, 3, 3, 7, 7, 9, 3, 6, 1, 3, 8, 8, 3, 7},
{3, 6, 8, 1, 5, 3, 9, 5, 8, 3, 8, 1, 8, 3, 3},
{8, 3, 2, 3, 3, 5, 5, 8, 5, 4, 2, 8, 6, 7, 6, 9},
{8, 1, 8, 1, 8, 4, 6, 2, 2, 1, 7, 9, 4, 2, 3, 3, 4},
{2, 8, 4, 2, 2, 9, 9, 2, 8, 3, 4, 9, 6, 3, 9, 4, 6, 9},
{7, 9, 7, 4, 9, 7, 6, 6, 2, 8, 9, 4, 1, 8, 1, 7, 2, 1, 6},
{9, 2, 8, 6, 4, 2, 7, 9, 5, 4, 1, 2, 5, 1, 7, 3, 9, 8, 3, 3},
{5, 2, 1, 6, 7, 9, 3, 2, 8, 9, 5, 5, 6, 6, 6, 2, 1, 8, 7, 9, 9},
{6, 7, 1, 8, 8, 7, 5, 3, 6, 5, 4, 7, 3, 4, 6, 7, 8, 1, 3, 2, 7, 4},
{2, 2, 6, 3, 5, 3, 4, 9, 2, 4, 5, 7, 6, 6, 3, 2, 7, 2, 4, 8, 5, 5, 4},
{7, 4, 4, 5, 8, 3, 3, 8, 1, 8, 6, 3, 2, 1, 6, 2, 6, 4, 6, 3, 8, 2, 9, 6},
{1, 2, 4, 1, 3, 3, 5, 3, 4, 9, 6, 3, 8, 6, 5, 9, 1, 5, 3, 2, 6, 8, 8, 5, 3},
{2, 2, 7, 9, 3, 3, 2, 8, 6, 9, 8, 4, 4, 9, 5, 8, 2, 6, 3, 4, 8, 4, 9, 3, 8, 8},
{7, 7, 7, 9, 7, 5, 2, 7, 9, 2, 5, 1, 9, 2, 6, 5, 3, 9, 3, 5, 7, 3, 5, 4, 2, 8, 9},
{7, 7, 6, 6, 8, 7, 5, 5, 8, 2, 4, 7, 7, 4, 7, 2, 6, 9, 2, 1, 8, 2, 9, 8, 5, 7, 3, 6},
{5, 9, 4, 5, 5, 7, 5, 5, 6, 3, 5, 3, 9, 5, 8, 9, 5, 4, 1, 2, 6, 1, 4, 3, 5, 3, 2, 4, 1}};
double[] w=new double[30];
double max;
double min;
for(int i=1;i<a.length;i++){
for(int j=0;j<a[i].length;j++){
if(j==0)a[i][0]+=a[i-1][0]/2;//最边缘的只平分上一行最边缘的重量
else if(j==a[i].length-1)a[i][j]+=a[i-1][j-1]/2;
else a[i][j]+=a[i-1][j-1]/2+a[i-1][j]/2;//不在边缘的平分左上和正上方的重量
}
}
max=min=a[28][0]/2;
for(int i=1;i<30;i++){//对最后一行体重秤进行赋值
if(i==0)w[i]=a[28][0]/2;//左边缘赋值
else if(i==29)w[i]=a[28][28]/2;//右边缘赋值
else w[i]=a[28][i]/2+a[28][i-1]/2;//其他赋值
if(w[i]>max)max=w[i];//找最大值
if(w[i]<min)min=w[i];//找最小值
}
System.out.println(max);
System.out.println(min);
System.out.println(max/min*2086458231);
}
答案:7.2665192664E10
思路:将数组每行每个数的重量平分给下一行,反复循环,一直累加到最后一行。
规律:下面每个重量=自身重量+正上方重量/2+左上方重量/2
2018年
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。
答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。(2+3i)^2 写成: -5+12i,(2+3i)^5 的写成: 122-597i
public static void main(String[] args){
long x=123456;
long a=2,b=3,c=2,d=3;
long n=a,m=b;
for(int i=1;i<x;i++){
n=a*c-b*d;
m=a*d+b*c;
// System.out.printf("a=%d,b=%d\n",n,m);
a=n;
b=m;
}
if(m<0)
System.out.println(n+""+m+"i");
else
System.out.println(n+"+"+m+"i");
}
答案:4043220979119144065-7374402350132176768i
思路:通过循环进行累乘求幂,最终得到结果
规律:(a*bi)*(c*di)=((a*c)-(b*d))+(a*d+b*c)i
注意:由于结果数值非常大,一定要用long型存数据,否则出来的答案不对。
结尾输出要做一下处理,否则答案不通过。
2019年
给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求第 20190324 项的最后 4 位数字。
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个 4 位整数(提示:答案的千位不为 0),在提交答案时只填写这个整数,填写多余的内容将无法得分。
public static void main(String[] args){
int[] a=new int[20190325];
int i;
a[0]=a[1]=a[2]=1;
for (i=3;i<20190324;i++){
a[i]=(a[i-3]+a[i-2]+a[i-1])%10000;//每次低四位求和得到的仍然取低四位
// System.out.println(a[i]);
}
System.out.println(a[i-1]);
}
答案:4659
思路:类似斐波那契数,循环求得前三项和的低四位并保存,再循环运算。
此题类似于斐波那契数列,但是所求20190324项的最后四位数字,要是单纯按照斐波那契数列的思想求下去,别说long类型,BigInteger类型都存不了这么大的数,然后我们发现,所求20190324项的最后四位数字(也就是变相的告诉我们运算过程只和每个数的后四位有关系),那么我们只需要保留每次运算结果的后四位就OK了,这样绝对不会溢出。
注意:一定要去理解%10000什么意思。就类似于你要取后三位数,无论多大的数多少个数进行求和,永远都是这几个数字的低三位求和得到最终的低三位数。
(比如2119+2220+2321+2422求这4个数和的低3位,就相当于只需要119+220+321+422=1082,再对1082%1000=082得到后三位)
2020年-1
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,A 国准备给大量民众进病毒核酸检测。然而,用于检测的试剂盒紧缺。为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k − 1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k + 1 个试剂盒完成了 k 个人的检测。A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?
(这道题需要用数学解题,由于本人数学不太好,所以直接借用其他博主的答案供大家参考)
均值不等式:
假设A国有n个人,感染者有n/100,每k个人一组,共n/k组,共用n/k瓶试剂,按照最坏的情况,每多出一个感染者就多用k瓶试剂,因此共用n/k+(n/100)*k瓶试剂n是定值,所以求(1/k+k/100)最小由于a+b>=2√ab,当且仅当a = b时,取等号,即1/k=k/100时,取得最小值。
解得k = 10
答案:10
思路:可以通过数学计算得到。也可以通过常识得到。做过核酸的应该都知道一管只能装10只拭子吧。
2020年-2
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …
…
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少?
public static void main(String[] args){
int a=1;
for(int i=1;i<20;i++){
a+=4*i;
}
System.out.println(a);
}
答案:761
思路:题目中给出了提示,第二行第二列是5,再通过观察发现对角线上每个数之间相差4的倍数,且有规律增长。根据这个规律可以求得最终结果
规律:对角线上呈等比数列。
2021年
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上2 × 3 个整点{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},即横坐标是0 到1 (包含0 和1) 之间的整数、纵坐标是0 到2 (包含0 和2) 之间的整数的点。这些点一共确定了11 条不同的直线。
给定平面上20 × 21 个整点{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},即横坐标是0 到19 (包含0 和19) 之间的整数、纵坐标是0 到20 (包含0 和20) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。
public static void main(String[] args){
HashSet<String> line=new HashSet<>();//HashSet存放无序但不重复的数组
HashSet<Integer> a = new HashSet<>();
for(int i=0;i<20;i++){//i表示横坐标
for(int j=0;j<21;j++){//j表示纵坐标
a.add(i*100+j);//a/100=i;a%100=y;
}
}
List<Integer> list=new ArrayList<>(a);//要想获取数组a中的数,就必须将数组a转成list类型进行获取
for(int i=0;i<20*21;i++){//固定一个点,在其余点中寻找符合条件的点
int x1=list.get(i)/100;//固定点x轴
int y1=list.get(i)%100;//固定点y轴
for(int j=i+1;j<20*21;j++){//固定点之后的所有点
int x2=list.get(j)/100;
int y2=list.get(j)%100;
int x=x1-x2;//两点x轴差值
int y=y1-y2;//两点y轴差值
if(x==0){//斜率不存在(垂直x轴)
String s=" "+x1;
line.add(s);//加入该直线
}
else {
int k=gcd(y,x);//求(y1-y2)/(x1-x2)最大公因数k(求得最简的K)
y=y/k;//化简x,y
x=x/k;
int b1=y1*x-x1*y;//求y1(x1-x2)-x1(y1-y2)。由于y=kx+b(将k=(y1-y2)/(x1-x2)带入得)->b=(y1(x1-x2)-x1(y1-y2))/(x1-x2)
int b2=x;//x1-x2
int b=gcd(b1,b2);//求b=(y1(x1-x2)-x1(y1-y2))/(x1-x2)
b1=b1/b;//化简b1,b2
b2=b2/b;
String s=y+" "+x+" "+b1+" "+b2;//将公式用字符串形式存入数组
line.add(s);//去重
}
}
}
System.out.println(line.size());
}
static int gcd(int a,int b){//求a,b最大公因数,即求最简的K
if(b==0)
return a;
return gcd(b,a%b);
}
答案:40257
思路:通过循环找到两个点,再通过递归找到这条直线的斜率和截距的最大公因数。最终得出这条直线的最简式并将其存入数组。所有点遍历完后,求得数组中不同直线的个数。
规律:找点-->求k-->求b-->存储。
注意:数字转字符串时一定要加" ",中间一定要有空格,否则会漏掉重复的。
2022年
给定一个只包含大写字母的字符串S,请你输出其中出现次数最多的字母。如果有多个字母均出现了最多次,按字母表顺序依次输出所有这些字母。
public static void main(String[] args){
Scanner input = new Scanner(System.in);
char[] s=input.nextLine().toCharArray();//输入字符串并将其存为字符数组
char[] count=new char[26];
for(int i=0;i<s.length;i++){//对相同字母进行计数
count[s[i]-'A']+=1;//这种写法值得学习
}
int max=count[0];
String str="";
for(int i=0;i<count.length;i++){//循环字母找最大值并以字符串形式存入str字串中
if(count[i]>max){
max=count[i];
str=""+(char)(i+'A');
}
else if(count[i]==max){
str+=(char)(i+'A');
}
}
System.out.println(str);
}
输入BABBACAC,输出AB
思路:将输入的字符串以字符形式存储,以字符ASCLL码为下标对相同字母进行计数。循环所有字母找出数量最多的并以字符串形式输出。