蓝桥杯JAVA组考前冲刺班题解与课堂重点内容记录(3.16)——特殊时间+卡片+约数个数

一、课堂重点内容:

1、枚举:个人见解为枚举就是一种知到一些必要的条件,然后从所有的数中选出一些符合条件的特殊的数字,比如我i们想要计算的是从1到10000之间的整数的和,我们就需要使用枚举的方法先将这些数字枚举出来,再进行计算,而在这个枚举的过程中,我们需要用到的方法是更具条件建立循环。再JAVA中常见的循环方式有三种,分别是while、for还有do while,其中的前两种更为常见

*while、do while和for的区分:若明确循环次数还有循环的条件,那么就使用for;

                                                 若不明确循环次数和循环条件,就需要使用do while或while

举个栗子,如lanqiaoOJ中的613题:

一个整数如果只含有因子3、5、7,称为幸运数字。 前10个幸运数字是3、5、7、9、15、21、25、27、35、45。 问59084709587505 是第几个幸运数字。

首先对题目进行分析:

循环条件:整数且只含有3、5、7这几个因子

循环次数:59084709587505

所以本题就是一个可以使用for循环来写的题目,具体的代码如下:

 

public class recview2023_3_16 {
public static void main(String args[])
	{
		long n=59084709587505L;//这是一个很大的数字,使用int无法完全表达,所以就需要使用一个比int还大的整形变量“long”
		//需要注意的是,long的最后需要加上一个‘L’或是‘l(小写的L)’
		int count=0;//定义一个整形变量count用于记录
		//因为这个数字的因数是3、5、7,所以这个数字写成是3^i*5^j*7^k
	for(int i=0;Math.pow(3, i)<n;i++)//3^i的最大值需要小于59084709587505
		{
		for(int j=0;Math.pow(5, j)<n;j++)
			{
				for(int k=0;Math.pow(7, k)<n;k++)
				{
					if(Math.pow(3, i)*Math.pow(5, j)*Math.pow(7, k)<n)//3、5、7的i、j、k次相乘小于59084709587505,那么就还不达到要求,需要继续循环
						count++;//在数值未达到要求前的每一个结果都符合整数如果只含有因子3、5、7,所以记录一次
				}
			}
		}
	System.out.println(count);//输出放在三个for循环外面,只有三个数的乘积大于59084709587505时才会输出,而输出的count就代表着59084709587505是第几个符合要求的数字
		
	}
}

2、组合

组合是一个很奇妙的东西,简单的来说就是在n个数字中,随机的选出m个,然后我们需要算出一共有多少种方法,上课的时候学长给了一个固定的模板,可以直接记忆,代码和解析如下:

static int m,n,ans;//先在整个Class里面定义m,n,ans三个整数,因为这三个整数通篇都可以用到,所以就可以使用static int的方法直接定义
	static Vector<Integer> chosen=new Vector<Integer>();//定义一个Vector数组
	public static void check(int x)//定义一个检查条件,用于去除不符合条件的数
	{
		if(chosen.size()>m||chosen.size()+(n-x+1)<m)//如果选择的数超出m或是剩下的数已经不够m个
			return;//那就直接返回
		if(x==n+1)//如果m的个数符合
		{
			String str="";
			for(int i=0;i<chosen.size();i++)
				System.out.print(chosen.get(i)+" ");//把当前的数组输出
			System.out.println("");
			ans++;//每输出一个数组就记录一次,表示这是第n个数组
			return;//返回继续判断
		}
		check(x+1);//判断x的下一个
		chosen.addElement(x);//将指定的分量添加到此向量的末尾,将其大小增加 1。如果此向量的大小大于其容量,则其容量将增加。
		check(x+1);//判断上一步中的结果
		chosen.remove((Object)x);//删除此 Vector 中指定元素的第一个匹配项如果 Vector 不包含该元素,则它保持不变。也可以认为是删除具有最低索引i的元素,以便Objects.equals(o,get(i))(如果存在这样的元素)。
	}
	public static void main(String args[])
	{
		Scanner sc=new Scanner(System.in);//输入语句
		n=sc.nextInt();//输入样本总数
		m=sc.nextInt();//从中挑选m个
		check(1);//从1开始
		System.out.println(ans);//输出统计结果
	}

3、排列

排列枚举和组合枚举大体上相似,但是排列枚举多了一些限制,先展示代码,解析会在后面另行补充

static  int n;
static int[] order =new int[20];
static boolean[] chosen =new boolean[20];
static <object> void calc(int x) {
    if (x == n + 1) { //选够了m个数输出
        String ansTem = "";
        for (int i = 1; i <=n ; i++)
            System.out.println(order[i]);
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (chosen[i]) continue;
        order[x] = i;
        chosen[i] =true;
        calc(x + 1);
        chosen[i] = false;
        order[x] = 0;
    }
}
public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    n = in.nextInt();
    for (int i = 0; i < n; i++) {
       String s;
        s=in.next();
        name.addElement(s);
    }
    calc(1);
}

二、课后练习题

1、约数个数

1200000 有多少个约数(只计算正约数)。

这是一个很简单的暴力枚举题,代码及解析如下:

public class Main
{
public static void main(String args[])
	{
		int ans=0,n=1200000;//定义一个ans用于记录,目标数值是1200000
		for(int i=1;i<=n;i++)//一个数的约数一定小于等于这个数的本身,所以从1开始取余数,一直取到这个数本身。
		{
			if(n%i==0)//要是余数为0,就说明这个数是1200000的约数
				ans++;//个数加1
		}
		System.out.println(ans);//输出个数的总数
	}
}

2、特殊时间

本体的重点在于年月日加时间中所有的数字一共有两种,而且这两种数字出现的比例为3:1

代码与详细解析如下:

public class Main
{
static int P[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//先把每个月的天数考虑出来,在本题中0229是一个违法数字,所以我们不用考虑闰年
	static int checkD(int D)//先定义一个子函数用于检查日期的合法性
	{
		int month=D/100;//取出前两位是月份
		int day=D%100;//取出后两位是日期
		if(month<1||month>12) return 0;//非法,则返回0
		if(day<1||day>P[month])return 0;
		return 1;//合法,则返回1
	}
	static int checkH(int H)//检时间的合法性
	{
		int h=H/100;//取出前两位是小时
		int m=H%100;//取出后两位是分钟
		if(h<0||h>23)return 0;//非法,则返回0
		if(m<0||m>59)return 0;
		return 1;	//合法,则返回1
	}
	public static void main(String args[])
	{
		int ans=0;//定义一个为0的整数用于记录
		for(int a=0;a<=9;a++)//定义组成日期的a,b两个数,两个数的取值范围都属0——9
			for(int b=0;b<=9;b++)
				if(a!=b)//a和b不相等是前提
				{
					int A[]=new int[] {a,a,a,a};//先定义一个全都是a的数组
					int NY=4,ND=0,NH=0;//分别定义合法排序的初始值,因为年份没有非法情况,所以可以直接定于为4(a,a,a,b)、(a,a,b,a)、(a,b,a,a)、(b,a,a,a,)
					for (int i=0;i<4;i++)//每个小分组一共有4位数,所以把他们拆开在分别替换成b的值
					{
						A[i]=b;//把第i个数替换成b当前的数值
						int number=0;
						for(int j=0;j<4;j++)//把被拆散的四位数还原
							number=number*10+A[j];
						ND+=checkD(number);//判断当前的四位数是否是合法月份+日期
						NH+=checkH(number);//判断当前的四位数是否是合法的时间
						A[i]=a;//将替换成b的数还原为a
					}
					ans+=NY*ND*NH;//所有的种类等于三个部分的所有可能的乘积
				}
		System.out.println(ans);//输出该乘积,就是所有符合条件的合法日期
	}
}

3、卡片

小蓝有很多数字卡片,每张卡片上都是数字 00 到 99。

小蓝准备用这些卡片来拼一些数,他想从 11 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。小蓝想知道自己能从 11 拼到多少。例如,当小蓝有 3030 张卡片,其中 00 到 99 各 33 张,则小蓝可以拼出 11 到 1010,但是拼 1111 时卡片 11 已经只有一张了,不够拼出 1111。现在小蓝手里有 00 到 99 的卡片各 20212021 张,共 2021020210 张,请问小蓝可以从 11 拼到多少?

这个题目看起来有些难度,但是仔细阅读就会发现这是一个消耗1的问题,把所有的1消耗完就不可以再拼出新的数字了。

简单的解决方法是直接借助word文档就可以

public class Main{
public static void main(String args[])
	{
		for (int i=0;i<20202;i++)
			System.out.println(i);
	}

}

直接使用java打赢一个较大的数,然后全选复制粘贴到word文档中,然后再找到第2021个1,其对应的数就是我们要找的数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值