1、题目描述
小刘是个儿孙满堂的1,所有的质数都是他的子女,除了他的子女外,他还有许多孙子,小刘的孙子都是合数。如果一个合数由两个质数相乘而得,那么这个合数就是小刘的直系孙子。小刘年事已高,忘记了哪些是他的直系孙子了,现在,给你一系列自然数,判断它们是否是小刘的直系孙子
抓重点
最终要求:判断给定的自然数是否是小刘的直系子孙
给定条件:
- 小刘是一个儿孙满堂的1,所以给定的自然数中不可能再出现1
- 所有的质数都是他的子女,质数:只能被1和该数本身整除的数
- 孙子是合数,合数:除了1和该数本身还能被其他数整除的数,如果一个合数由两个质数相乘而得那么就是小刘的直系子孙。
输入
第一行一个正整数T,表示需要判断的自然数数量接下来T行,
每行一个要判断的自然数
输出
共T行,依次对于输入中给出的自然数,判断是否为小刘的直系孙子,是则输出Yes,否则输出No
演示
输入样例
4
3
4
6
12
输出样例
No
Yes
Yes
No
代码实现
import java.util.Scanner;
public class Main {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
int length = scanner.nextInt();//输入数的个数
int[] number = new int[length];//使用数组存放输入的数
String[] result = new String[length];//使用字符串数组存放结果
for(int i = 0; i < length; i++){//遍历输入
number[i] = scanner.nextInt();
}
for(int i = 0; i < length; i++){//遍历number中的数据
int value = number[i];//拿到数组中的数据
boolean flag = false;//设定一个标志位,方便结果的存放
if(!isPro(value)){//判断输入的数据是否是合数,如果不是合数就不是小刘的子孙
for(int j = 2; j < value; j++){ //遍历该数的子元素,
int temp = value / j; //利用整除的方式得到另一个子元素
//判断两个子元素是否都是质数,并且两个子元素相乘是否是输入的那个数
if(isPro(j) && temp * j == value && isPro(temp)){
flag = true;//修改标志位
//给value重新赋值,以此方法来控制遍历子元素的循环停止
value = value % j;
}
}
result[i] = flag ? "Yes" : "No"; //利用标志位来存放结果
}else{
result[i] = "No";//如果输入的数不是合数就直接不是小刘的子孙
}
}
//遍历输出结果
for(int i = 0; i < length; i++){
System.out.println(result[i]);
}
}
//判断是否是质数,否则就是合数
private static boolean isPro(int n){
//使用开根号的形式判断素数,能减少很多次运行,大大的节约了程序的运行成本
for(int i = 2; i <= Math.sqrt(n); i++){
if(n % i == 0) return false;
}
return true;
}
}
总结
这道题目是ACM中的基础题,很简单但是很有意思。
我个人觉得我这段代码写的还是不错的,有点小开心,嘿嘿!
for(int j = 2; j < value; j++){ //遍历该数的子元素,
int temp = value / j; //利用整除的方式得到另一个子元素
//判断两个子元素是否都是质数,并且两个子元素相乘是否是输入的那个数
if(isPro(j) && temp * j == value && isPro(temp)){
flag = true;//修改标志位
//给value重新赋值,以此方法来控制遍历子元素的循环停止
value = value % j;
}
}
但是有点不足之处,在循环的时候,无论是质数还是合数,都会循环到,所以还是做了不必要的运行到,如果能直接运行质数的话,运行的时间又会减少大半。
不断的改造不断的优化,这不就是代码的魅力所在吗?