目录
题目链接:0幸运数字 - 蓝桥云课 (lanqiao.cn)
解法
思路
高级思路
总结
题目链接:0幸运数字 - 蓝桥云课 (lanqiao.cn)
解法
首先是我写了差不多一个小时的解法,裂开了,为什么我如此废物
思路
寻找第2023个在二进制、八进制、十进制和十六进制表示下都为哈希德数的整数
在main函数中通过一个while循环来遍历所有的整数,直到找到第2023个满足条件的整数。position
变量用于记录已经找到多少个满足条件的整数。
在每次循环中,首先通过调用getEachSum(i)
函数计算整数i
在十进制下各个位数之和。如果i
不能被这个和整除,那么就继续检查下一个整数。
如果i
能被这个和整除,那么就把i
转换成二进制字符串,并计算字符串中所有字符(除去字符'0')的数量,这也就是二进制下各位之和。再检查i
是否能被这个和整除,如果不能,那么就继续检查下一个整数。
接着,把i
转换成八进制的形式,然后用getEachSum(octal)
计算这个八进制数的各位之和,并检查i
是否能被这个和整除,如果不能,那么就继续下一个整数。
再然后,把i
转换成十六进制字符串,并计算字符串中所有字符对应的数值之和。这一步中,有一个try...catch结构,这是因为十六进制数包括0-9和a-f两部分,对于a-f,用字符的阿斯奇码值减去'87'来得到对应的数值。再检查i
能否被这个和整除,如不能,继续下一个整数。
如果i
能被所有这些和整除,那么就意味着i
在二进制、八进制、十进制和十六进制下都是哈希德数,于是就把它放入数组arr
中,并使position
加一,然后继续检查下一个整数。
getEachSum
函数的作用是计算一个十进制数各位数之和,如果输入是非十进制的数,那么必须先将其转换为十进制。
一直到找到第2023个满足条件的整数,然后结束循环,输出这个整数。
是不是很流畅但是写的太复杂了,然后我去看了看其他大佬的题解,就发现了另一个结题思路
package src;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
//1:无需package
//2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) throws IOException {StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));// 如果一个整数在二,八,十,十六进制下都可以被条件整除记录int position = 1;int i = 1;long res = -1;long[] arr = new long[2023];while (position <= 2023) {long sum = getEachSum(i);boolean flag = true;// 判斷是否十进制符合if (i % sum != 0) {i++;continue;}// 判斷是否二进制符合String strBinary = Integer.toBinaryString(i);char[] binary = strBinary.toCharArray();sum = 0;for (char c : binary) {sum += c - 48;}if (i % sum != 0) {i++;continue;}// 判斷是否八进制符合long octal = Integer.parseInt(Integer.toOctalString(i));sum = getEachSum(octal);if (i % sum != 0) {i++;continue;}// 判斷是否十六进制符合 2aString strHex = Integer.toHexString(i);char[] strS = strHex.toCharArray();sum = 0;for (char c : strS) {try {sum += Integer.parseInt(c + "");} catch (Exception e) {// TODO: handle exceptionsum += c - 87;}}if (i % sum != 0) {i++;continue;}// 如果走到这里说明全部符合res = i;arr[position - 1] = res;position++;i++;}System.out.println(res);}public static long getEachSum(long num) {long res = 0;while(num > 0) {long one = num % 10;res += one;num /= 10;}return res;}
}
通过这段不太聪明的代码之后就成功的跑出来了。
高级思路
main
函数里首先,声明了一个计数变量cnt
,设置初始值为0。接着,进入一个无限循环,每次循环都会将i
(起始值为1)作为待检查的数字,
然后,调用check
函数检查这个数字在二进制、八进制、十进制和十六进制(也就是Mod 2, 8, 10 和 16)中是否都是哈希德数。 如果这个数字在所有这些进制下都是哈希德数,那么将计数变量cnt
加1。 然后检查cnt
是否等于2023,如果是,那么就输出当前的数字i
并退出循环。如果不是,那么就将i
增加1,并开始下一个循环,继续检查下一个数字。
重要的,高级的来哦了,check
函数是用于检查一个数字在给定进制下是否是哈希德数的函数。它接受两个参数,x
代表待检查的数字,mod
代表要将x
转换成哪种进制。函数内部,首先复制x
的值给n
保存,然后通过一个循环,计算转换为mod
进制下的各位数值和ans
。如果n
可以被ans
整除,那么就返回真(即该数在给定进制下是哈希德数),否则返回假。
我来特别解释一下check函数
在check
函数中,while
循环是用来计算一个给定整数x
在特定进制mod
下所有位上数字之和的。
整个流程是这样的:
-
初始化
ans
为0,这个变量用来存储x
在特定进制下所有位上数字之和。 -
进入
while
循环,只要x
大于0,就一直执行循环。 -
在每次循环中,
x
对mod
取余(即x % mod
),这相当于得到x
在mod
进制下的最低位。根据余数定理和我们的进制制度,当一个数对某个进制进行取余操作时,得到的余数就是该数在这种进制下的最低位。(大家可以回想一下自己求十进制数的个位的时候是不是就是这个操作) -
把取得的最低位加到
ans
里,ans
在循环过程中始终记录了x
在mod
进制下所有已经处理过的位的和。 -
然后用
x
除以mod
(即x / mod
),结果赋值给x
,这相当于把x
在mod
进制下的最低位去掉。再次运用余数定理和我们的进制制度,当一个数被某个进制的数除时,结果就是这个数在这种进制下去掉最低位的部分。 -
这个循环反复执行,直到
x
小于等于0,也就是我们说的x
已经没有剩下位数要处理。
所以这个while
循环的作用就是,将一个给定的数x
在给定的进制mod
下的所有位上的数字全部加起来,结果存放在ans
中。
我只能说天才
所以说,这段代码的功能就是找出第2023个在2、8、10、16进制下都是哈希德数的数字。
public class Main {public static void main(String[] args) {int cnt = 0;for(int i=1; ; i++){if(check(i, 2) && check(i, 8) && check(i, 10) && check(i, 16)) cnt++;if(cnt == 2023){System.out.println(i);break;}}}//判断是否为mod进制下的哈沙德数public static boolean check(int x, int mod){int n = x;int ans = 0;while(x>0){ans = ans+ x%mod;x /= mod;}return n%ans==0;}
}
总结
大佬就是大佬,蓝桥杯四个小时,这道题我写了一个小时,我已经废了
再见