方法一:枚举
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int min = (int) (1*Math.pow(10,n-1));
int max = min *10 - 1;
for (int i = min; i <= max; i++) {
if(f(i,n)) System.out.println(i);
}
}
private static boolean f(int i,int n) {
for (int j = 0; j < n; j++) {
if(isprime(i)){
i/=10;
continue;
}
return false;
}
return true;
}
private static boolean isprime(int x) {
if(x<2) return false;
int t = (int) Math.sqrt(x);
for (int i = 2; i <= t; i++) {
if(x%i == 0) return false;
}
return true;
}
}
这个方法超时了。
方法二:dfs
上面的方法是先列出所有可能,再挨个挨个判断,比如先判断7331、 再判断733、再判断73.......,在列出可能的时候,有很多的数据很显然是没有用的,如果我们反过来,先判断7、再判断73、再判断733....这样进行递归判断,就不需要枚举那么多的数据。
import java.util.Scanner;
public class Main {
static int n;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
dfs(0,1);
}
//x表示前面长度为length-1的数,
public static void dfs(int x,int length) {
if(length>n) //满足长度时输出
{
System.out.println(x);
}
else {
for (int i = 1; i <= 9; i++) {
if(isprime(x*10+i))
{
dfs(x*10+i, length+1);
}
}
}
}
private static boolean isprime(int x) {
if(x<2) return false;
int t = (int) Math.sqrt(x);
for (int i = 2; i <= t; i++) {
if(x%i == 0) return false;
}
return true;
}
}
三:对方法二的改进
经过分析可知,第一位的数字只能是2、3、5、7,后面的每一位只能是1、3、7、9(2或5结尾的不是质数),我们只需要对这些组合进行判断即可。
import java.util.Scanner;
public class Main {
static int n;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
int[] a= {2,3,5,7};//第一个数
for (int i = 0; i < a.length; i++) {
dfs(a[i],1);
}
}
private static void dfs(int x, int len) {
if(len == n){
if(isprime(x)){
System.out.println(x);
}
}
if(isprime(x)){
//考虑每种组合
dfs(x*10+1,len+1);
dfs(x*10+3,len+1);
dfs(x*10+7,len+1);
dfs(x*10+9,len+1);
}
}
private static boolean isprime(int x) {
if(x<2) return false;
int t = (int) Math.sqrt(x);
for (int i = 2; i <= t; i++) {
if(x%i == 0) return false;
}
return true;
}
}