🍋1.快速求最大公约数及最小公倍数
这个考点我相信大家一定不陌生,求最大公约数有的人可能还用的是遍历去查询,如果是填空题时间长点可能无所谓,但是如果大题涉及到最大公约数或者公倍数的问题,蓝桥杯的数据量是出名的大(这个后面会体现),超时是肯定的。所以请大家背下欧几里得公式直接使用(已知效率最快求出公倍数地公式)
1.gcd函数(欧几里得算法原理)
//返回值则是a和b的最大公约数 int gcd(int a,int b){ return b == 0 ? a:gcd(b,a%b); }
2.lcm函数(速求最小公倍数,原理基于gcd函数)
//返回值为a和b的最小公倍数 int lcm(int a, int b){ return a/gcd(a,b)*b;//最小公倍数=两数之积÷两数最大公约数 }
☀️1.1既约分数
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如,3/4,1/8,7/1 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1和 2020)?
题目链接:既约分数https://www.lanqiao.cn/problems/593/learning/
这道题是一道填空题,在真实的考试环境下我们即使使用朴素求最大公约数的方法仍然可以抛出答案,但在蓝桥官方的oi平台是会超时的,根据题意利用欧几里得公式可以直接写出代码。
import java.util.Scanner; public class Main { static int ans=0; public static void main(String[] args) { for(int i=1;i<=2020;i++){ for(int j=1;j<=2020;j++){ if((gcd(i,j)==1)) ans++; } } System.out.println(ans);//答案为2481215 } static int gcd(int a,int b){ return b == 0 ? a:gcd(b,a%b); } }
🌁 1.2分数
1/1+1/2+1/4+1/8+⋯
每项是前一项的一半,如果一共有 20 项,求这个和是多少,结果用分数表示出来。
类似:3/2,当然,这只是加了前 2 项而已。分子分母要求互质。
题目链接:分数https://www.lanqiao.cn/problems/610/learning/
这道题比较简单,我们求出分子和分母即可。不过题目要求互质,所以我们可以应用gcd函数求出分子和分母的最大公约数进行约分。
public class 分数 { public static void main(String[] args) { //x为分母 int x=1; //count为分子 int count=1; for(int i=2;i<=20;i++) { x*=2; count+=x; } //打印一下分子分母看看 System.out.println(x);//524288 System.out.println(count);//1048575 int a=gcd(x,count);//最大公约数发现就为1 int b=x/a; int d=count/a; //打印答案 System.out.println(d+"/"+b);//1048575/524288 } static int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } }
🍋2.对于日期的处理能力(重点)
考察日期的处理,这几乎是蓝桥杯每届必考的考点。这一点我在前面的蓝桥真题中也提起过,大家可以通过上面的链接去看。Java组的同学必须学会使用Calendar这个函数,它能快速求出某年某月某日是星期几,这对于繁杂的日期处理题来说,简直是神器。
☔️2.1世纪末的星期
题目:有邪教称1999年12月31日是世界末日,当然谣言已经不攻自破。还有人称今后的某个世纪末的12月31日,如果是星期一则会....有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!!于是"谣言制造商"又修改为星期日.......
1999年12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即XX99年)的12月31日正好是星期天(即星期日)? 回答年份即可
这是一道很久远的一道蓝桥真题(还是第一题),按道理蓝桥杯的第一题都是一眼能得出答案的,但是这道题按照常规的方法来处理还是有点麻烦的。但通过Calendar却可以秒杀这道题。
public class 世纪末的星期 { public static void main(String[] args) { //注意Calendar实例的获取方式 Calendar calendar = Calendar.getInstance(); for (int year = 1999; year <10000 ; year+=100) { //设置年月日 calendar.set(Calendar.YEAR,year); calendar.set(Calendar.MONTH,11);//其实是12月 calendar.set(Calendar.DAY_OF_MONTH,31); //判断是星期几 if (calendar.get(Calendar.DAY_OF_WEEK)==1) { //sunday是第一天,所以为1时是Sunday,通过源码查看 System.out.println(year);// 2299 break; } } } }
☁️2.2跑步锻炼
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年 10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
题目链接:跑步锻炼https://www.lanqiao.cn/problems/597/learning/
这道题目需要我们去进行日期的模拟,用一个数组去表示每个月的日子,对于闰年的二月去进行特判。
public class 跑步锻炼 { static int[] M={0,31,28,31,30,31,30,31,31,30,31,30,31}; public static void main(String[] args) { int y = 2000, m = 1, d = 1, w = 6, ans = 0; while(y!=2020 || m!=10 || d!=1){ if(y%400==0 || (y%4==0&&y%100!=0)){ M[2] = 29; } else{ M[2] = 28; //M是全局变量 } d++; w = (w + 1) % 7;//w为0为星期天 if(d > M[m]){ d = 1; m ++; } if(m>12){ m = 1; y ++; } if(d==1 || w==1){ ans++; //是月初或者周一多加一次 } ans++; } //这个循环是先加值再加日期,所以2020.10.1号的已经加上去了,但是2000.1.1没加上,所以加2 ans+=2; System.out.println(ans);//8879 } }
❄️2.3星期一
整个 2020 世纪(1901 年 1 月 1 日至 2000 年 12 月 31 日之间),一共有多少个星期一?
题目链接:星期一https://www.lanqiao.cn/problems/611/learning/
同样是日期模拟的问题,需要去判断星期一的个数。这道题我的思路是结合上面两道日期题的做法。先利用Calendar算出起始日期和结尾日期是星期几。再利用跑步锻炼题目的模板结合模拟。可以算出答案为5217。
为什么要知道起始是星期几?
因为这个代码模板需要知道起始的日期,而最后一天2000年12月31日是没有在循环中判断的。我们需要特判一下,当然我们也可以让循环在2001年1月1日结束,这样不需要特判。
public class 星期一 { static int[] M={0,31,28,31,30,31,30,31,31,30,31,30,31}; public static void main(String[] args) { Calendar c=Calendar.getInstance(); c.set(Calendar.YEAR, 1901); c.set(Calendar.MONTH, 0); c.set(Calendar.DAY_OF_MONTH, 1); System.out.println(c.get(Calendar.DAY_OF_WEEK));//3所以为星期二 Calendar c2=Calendar.getInstance(); c2.set(Calendar.YEAR, 2000); c2.set(Calendar.MONTH, 11); c2.set(Calendar.DAY_OF_MONTH, 31); System.out.println(c2.get(Calendar.DAY_OF_WEEK));//1 所以是星期天 test(); } static void test() { int y = 1901, m = 1, d = 1, w = 2, ans = 0; while(y!=2000 || m!=12 || d!=31){ if(y%400==0 || (y%4==0&&y%100!=0)){ M[2] = 29; } else{ M[2] = 28; //这个必须加,因为M为全局变量 } d++; w = (w + 1) % 7;//w为0为星期天 if(d > M[m]){ d = 1; m ++; } if(m>12){ m = 1; y ++; } if(w==1){ ans++; //是周一就加 } } //我们已经知道2000.12.31不是星期1,不需要特判 System.out.println(ans);//5217 } }