【蓝桥杯】第202420242024 个报数游戏

蓝桥杯官网原文:202420242024 个被报出的数是多少

一、方法1(秒杀型)

解题思路

通过观察发现,第奇数位个数是20的倍数,第偶数位个数是24的倍数。所以第202420242024个数

就是24的倍数,那我们直接除以2(判断是这个数是第几个24的倍数),然后再乘24就行。

也就是202420242024÷2×24=2429042904288

源代码

public class Main {
	public static void main(String[] args) {
		long no = 202420242024L;
		doTest1(no);
	}
	static void doTest1(long num) {
		System.out.println(num / 2 * 24);
	}
}

二、方法2(普通归纳演绎性)

解题思路A

(1)在草稿纸枚举了前20个数。

第1-10个: 20 24 40 48 60 72 80 96 100 120。

第11-20个:140 144 160 168 180 192 200 216 220 240。

(2)发现从0到第10个数的间隔是20,4,16,8,12,12,8,16,4,20。发现从10到第20个数的间隔也是20,4,16,8,12,12,8,16,4,20。大胆推测十个数就是一个周期轮回。从0开始,每个周期内,十个数之间的间距(差值)分别是20,4,16,8,12,12,8,16,4,20。

(3)每个周期之间的间距为20+4+16+8+12+12+8+16+4+20,或者直接120(即120-0)

(4)第 202420242024 个报数为20242024202个周期(即202420242024/10),然后再加上4(即202420242024%10)。也就是202420242020/10*120=202429042904240,找它之后的四个能被20或24整除的数。

解题思路B

(1)在草稿纸枚举了前40个数得出来的

第1-10个: 20 24 40 48 60 72 80 96 100 120

第11-20个:140 144 160 168 180 192 200 216 220 240

第21-30个:260 264 280 288 300 312 320 336 340 360

第31-40个:380 384 400 408 420 432 440 456 460 480

(2)发现第10个数,第20个数,第30个数,第40个数......(每十个数为一轮)等等都是120的倍数,

(3)既然题目要求第202420242024个数,那我们不妨先求第202420242020个数,然后再往后再多求4个数就行。也就是202420242020/10*120=202429042904240,找它之后的四个能被20或24整除的数,也就是2429042904288

源代码

对于本方法,思路A和思路B异曲同工,代码本质上一样。因此,下面只给出一份源代码。

public class Main {
	public static void main(String[] args) {
		long no = 202420242024L;
		doTest2(no);
	}
	static void doTest2(long num) {
		long h = num / 10;
		int low = (int) (num % 10);
		long k = 0;
		// 20+4+16+8+12+12+8+16+4+20;
		long n = 120 - 0;
		long m = h * n;
		while (k < low) {
			m = m + 4;
			if (m % 20 == 0 || m % 24 == 0) {
				k++;

			}
		}
		System.out.println(m);
	}
}

三、方法3(通用归纳演绎性)

解题思路

(1)在草稿纸枚举了前20个数。

第1-10个: 20 24 40 48 60 72 80 96 100 120。

第11-20个:140 144 160 168 180 192 200 216 220 240。

第21-30个:260 264 280 288 300 312 320 336 340 360

(2)发现从0到第10个数的间隔是20,4,16,8,12,12,8,16,4,20。发现从10到第20个数的间隔也是20,4,16,8,12,12,8,16,4,20。大胆推测十个数就是一个周期轮回。从0开始,每个周期内,十个数之间的间距(差值)分别是20,4,16,8,12,12,8,16,4,20。

同时注意到:第十个数120是20和24之间的最小公倍数,第二十个数240是最小公倍数120*2,第三十个数360是最小公倍数120*3,轮回周期就是最小公倍数

(3)用变量a代表20,变量b代表24,计算出他们最小公约数gcd和最小公倍数(既轮回周期step),以及周期内能被a或者b整除数的个数n

(4)第k 个报数,即为k/n个周期,然后再加上k%n个报数。也就是k/n*step,找它之后的k%n个能被a或b整除的数。

源代码

public class Main {
	public static void main(String[] args) {
		long k = 202420242024L;
		doTest3(k, 20, 24);
//		k = 20242024L;
//		doTest3(k,20,24);
//		doTest4(k,20,24);
//		doTest3(k,20,28);
//		doTest4(k,20,28);
	}

	static void doTest3(long num, int a, int b) {
		// TODO Auto-generated method stub
		int gcd = getGCD(a, b);
		// 最小公倍数求解
		int step = a / gcd * b;
		//周期内被a和b整除数的个数
		int n = count(0, step, a, b, gcd);
		long h = num / n;
		int low = (int) (num % n);
		long k = 0;
		long m = h * step;
		while (k < low) {
			m = m + 4;
			if (m % 20 == 0 || m % 24 == 0) {
				k++;

			}
		}
		System.out.println(m);
	}

	static void doTest4(long num, int n1, int n2) {
		// 暴力求解
		long i = 1;
		int count = 0;
		while (true) {
			i += 1;
			if (i % n1 == 0 || i % n2 == 0) {
				count++;
			}

			if (count == num) {
				break;
			}
		}
		System.out.println(i);
	}

	/*
	 * 寻找从start到end之间,能被a或b整除的数个数.如果公约数gcd小于1,则内部再根据a和b计算
	 */
	static int count(int start, int end, int a, int b, int gcd) {
		long temp = start;
		int count = 0;
		if (gcd < 1) {
			gcd = getGCD(a, b);
		}
		do {
			temp += gcd;
			if (temp % a == 0 || temp % b == 0) {
				// System.out.println(temp);
				count++;
			}
		} while (temp < end);
		return count;
	}

	/*
	 * 求最小公约数
	 */
	static int getGCD(int a, int b) {
		int min = a < b ? a : b;// 判断并取出两个数中小的数
		for (int i = min; i >= 1; i--) { // 循环,从最小值开始,依次递减,直到i=1
			if (a % i == 0 && b % i == 0) { // 当i能同时被A和B余尽时,返回i
				return i;
			}
		}
		return 1;
	}
}

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值