USACO - 1.5.2 - Prime Palindromes

 


原创文章转载请注明出处

摘要: 数论,质数 , 回文数

一. 题目翻译

1. 描述:
       因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
       写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数;

2. 格式:

          INPUT FORMAT:

          (file pprime.in)
          第 1 行: 二个整数 a 和 b .

          OUTPUT FORMAT:

          (file pprime.out)
          输出一个回文质数的列表,一行一个。

3. SAMPLE:
          SAMPLE INPUT:
5 500
          SAMPLE OUTPUT:
5
7
11
101
131
151
181
191
313
353
373
383

          
二.  题解
1. 题意理解(将问题分析清楚,大致用什么思路):
          参考了nocow上面的说明。
          我们的做法是从小到大生成一个回文数,然后判断是否为质数。生成回文数的方法是枚举产生从最高位到中间位的数,然后复制到低位即可(例如4位数,我们产生一个两位数作为第4位和第3位,然后复制到第2位和第一位)。
          这里有一个非常重要的优化就是所有的偶数回文数只有11是质数。也就是说我们只需要枚举产生奇数位的回文数即可,这样减少了一半的时间复杂度。

 

2.  具体实现(具体实现过程中出现的问题):
          我们根据输入的a来判断要产生的回文数是多少位的, 我们用jumpi==true表示需要跳过产生i位的回文数。例如:输入a=11111,那么jump1、jump3为true,表示我们不需要产生1位与3位的回文数,从5位的回文数开始产生,判断质数。

三.  代码

/*
ID:fightin1
LANG:JAVA
TASK:pprime
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;

public class pprime {
	public static void main(String[] args) {
		try {
			Scanner in = new Scanner(new BufferedReader(new FileReader(
					"pprime.in")));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(
					"pprime.out")));

			int a = in.nextInt();
			int b = in.nextInt();

			print(a, b, pw);
			pw.close();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static boolean isP(int num) {
		int mid =(int)Math.sqrt(num);
		for (int i=2;i<=mid;i++){
			if (num%i == 0){
				return false;
			}
		}
		return true;
	}
	
	public static int print(int a, int b ,PrintWriter pw){
		boolean jump1 = false ;
		boolean jump3 = false ;
		boolean jump5 = false ;
		boolean jump7 = false ;
		if (a > 11){
			jump1 = true ;
		} 
		if (a >=1000){
			jump1 = true ;
			jump3 = true ;
		}
		if (a >= 100000){
			jump1 = true ;
			jump3 = true ;
			jump5 = true ;
		}
		if (a>=10000000){
			jump1 = true ;
			jump3 = true ;
			jump5 = true ;
			jump7 = true ;
		}
		
		if (!jump1){
			for (int i = a;i<=9;i++){
				if(i>b){
					return 0;
				} else {
					if (isP(i)){
						pw.println(i);
					}
				}
			}
			pw.println("11");
		}
		if (!jump3){
			for (int i = 1;i<=9;i+=2){
				for (int j=0;j<=9;j++){
					int num = i*100 + j*10 + i;
					if (num <a){
						continue;
					} 
					if(num>b){
						return 0;
					} else {
						if (isP(num)){
							pw.println(num);
						}
					}
				}
				
			}
		}
		if (!jump5){
			for (int i = 1;i<=9;i+=2){
				for (int j=0;j<=9;j++){
					for (int k=0;k<=9;k++){
						int num = i*10000 + j*1000 + k*100 + j*10 + i;
						if (num <a){
							continue;
						} 
						if(num>b){
							return 0;
						} else {
							if (isP(num)){
								pw.println(num);
							}
						}
					}
				}
				
			}
		}
		if (!jump7){
			for (int i = 1;i<=9;i+=2){
				for (int j=0;j<=9;j++){
					for (int k=0;k<=9;k++){
						for(int m=0;m<=9;m++){
							int num = i*1000000 + j*100000 + k*10000 + m*1000 + k*100 + j*10 + i;
							if (num <a){
								continue;
							} 
							if(num>b){
								return 0;
							} else {
								if (isP(num)){
									pw.println(num);
								}
							}
						}
					}
				}
				
			}
		}
		return 0;
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值