PAT乙级测试题及JAVA参考例程

PAT就是浙江大学程序设计能力考试,网址为http://www.patest.cn。考试分为乙级、甲级和Top。这里分享一下乙级测试题和我实现的一些解法,如果有不同的解法或者更好的实现方式,欢迎在文章下面回复。主要是在提交的时候,需要注意编译器里为Main.class 所以主类的命名要为Main。

刷到第11题以后,java的劣势体现出来了,题库的时间限制都是针对c的,java读入数据的时间就可能会超过时间限制,所以后来我就没有继续刷题了,现在在牛客网刷PAT和其他在线测试,后续还会在更新其他题目。

1001. 害死人不偿命的(3n+1)猜想 (15)

卡拉兹(Callatz)猜想:

对任何一个自然数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。卡拉兹在1950年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证(3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……

我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过1000的正整数n,简单地数一下,需要多少步(砍几下)才能得到n=1?

 

输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。

 

输出格式:输出从n计算到1需要的步数。

 

输入样例:

3

输出样例:

5

这里第1题没有什么好说的,按照题目要求给出次数就好,代码如下。

import java.util.Scanner;

/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int num = Integer.parseInt(sc.nextLine());
        int step=0;
        
        while(num >1){
            if(num%2 == 0){
                num = num/2;
                step++;
            }
            else{
                num = (3*num+1)/2;
                step++;
            }
        }
        System.out.println(step);
        
    }
}

1002. 写出这个数 (20)

读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10100。

 

输出格式:在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格。

 

输入样例:

1234567890987654321123456789

输出样例:

yi san wu

这个题一般也不会遇到什么问题,各个数位求和,然后求出和的每一位数,并且用switch语句和0到9的拼音匹配就好。代码如下:

import java.util.Scanner;
import java.util.Stack;

/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String numString = sc.next();

        int num = 0;
        int sum = 0;
        for(int i=0; i stack = new Stack();
       String output = new String();
       String outtemp = new String();
       int temp;
       int flag = 0;
       if(num ==0)
           output += "ling";
       while(num>0){
           stack.push(num%10);
           num = num/10;
       }
       while(!stack.empty()){
           temp = stack.pop();
           switch(temp){
                case 0: outtemp = "ling";
                    break;
                case 1: outtemp = "yi";
                    break;
                case 2: outtemp = "er";
                    break;
                case 3: outtemp = "san";
                    break;
                case 4: outtemp = "si";
                    break;
                case 5: outtemp = "wu";
                    break;
                case 6: outtemp = "liu";
                    break;
                case 7: outtemp = "qi";
                    break;
                case 8: outtemp = "ba";
                    break;
                case 9: outtemp = "jiu";
                    break;
                    
           }
           if(flag ==0){
               output += outtemp;
               flag = 1;
           }
           else{
               output =output+ " " +outtemp;
           }
       }
       System.out.println(output);
    }
}

1003. 我要通过!(20)

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送—— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

 

1. 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;

2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;

3. 如果 aPbTc 是正确的,那么aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

 

现在就请你为PAT写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

输入格式:每个测试输入包含1个测试用例。第1行给出一个自然数n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过100,且不包含空格。

 

输出格式:每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出YES,否则输出NO

 

输入样例:

 

8

PAT

PAAT

AAPATAA

AAPAATAAAA

xPATx

PT

Whatever

APAAATAA

输出样例:

YES

YES

YES

YES

NO

NO

NO

NO

这个题目会存在一些小小的问题,主要是对于题目的理解不是很到位引起的。

 

首先我们看题目的意思,1和2两点没有问题,主要是第3点,其实第3点是对第2点的推广。理解了这一点之后,就可以发现规律了。其实从2我们可以发现,在1 2的约束下,满足条件的只有两种形式PAT和APATA,那么3中满足条件的必然是从2推导出来的。

 

1.如果初始的是PAT那么接下来就是PAAT,再接下来就是PAAAT,以此类推。

 

2.如果初始状态是aPATa的话,那么接下来就是aPAATaa,在接下来就是aPAAATaaa,其中a为A的字符串,我们发现num(P前面a)*num(A)=num(T后面a),上面的形式也满足这个条件,所以我们可以利用这个约束来判断。下面是代码部分:

import java.util.Scanner;

/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        for(int i=0; i=1 && nump==1 && numt==1){
                //System.out.println(str.indexOf('P'));
                //System.out.println(str.indexOf('T'));
                if(str.indexOf('P')*(str.indexOf('T')-str.indexOf('P')-1) == str.length() - str.indexOf('T')-1)
                    flag = true;
                else
                    flag = false;
            //str.indexOf('P')*(str.indexOf('T')-str.indexOf('P'));
            //int numAbeforeP = str.indexOf('P');
            }
            if(flag)
                System.out.println("YES");
            else
                System.out.println("NO");
        }
        
    }
}

1004. 成绩排名 (20)

读入n名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。

输入格式:每个测试输入包含1个测试用例,格式为

 

  第1行:正整数n

  第2行:第1个学生的姓名 学号 成绩

  第3行:第2个学生的姓名 学号 成绩

  ...... ...

  第n+1行:第n个学生的姓名 学号 成绩

其中姓名和学号均为不超过10个字符的字符串,成绩为0到100之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。

输出格式:对每个测试用例输出2行,第1行是成绩最高学生的姓名和学号,第2行是成绩最低学生的姓名和学号,字符串间有1空格。

 

输入样例:

3

Joe Math990112 89

Mike CS991301 100

Mary EE990830 95

输出样例:

Mike CS991301

Joe Math990112

这一题有几个注意点需要注意:

1.当n=1的时候需要处理,此时应该输出两行一样的姓名和学号

2. 由于提交的jdk版本是jdk1.6 不支持,自己实现Comparator接口,覆盖compare方法的sort,所以我这里使用了Collections.sort()进行排序,代码如下

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

/**
 *
 * @author zjb
 */
public class Main{
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int rp = sc.nextInt();
        String studentInfo = new String();
        studentInfo = sc.nextLine();
        List studentList = new ArrayList();
        List studentscore = new ArrayList();
        for(int i=0; i

1005. 继续(3n+1)猜想 (25)

卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。

当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在验证3的时候遇到过了,我们称5、8、4、2是被3“覆盖”的数。我们称一个数列中的某个数n为“关键数”,如果n不能被数列中的其他数字所覆盖。

现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。

 

输入格式:每个测试输入包含1个测试用例,第1行给出一个正整数K(<100),第2行给出K个互不相同的待验证的正整数n(1

 

输出格式:每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用1个空格隔开,但一行中最后一个数字后没有空格。

 

输入样例:

6

3 5 6 7 8 11

输出样例:

7 6

这个题就是1001的延续,这里对每一个输入的数字,都遍历一边整个输入的验证过程,这种方式比较消耗内存,可以看到我在这里使用了3个ArrayList,

还有一种方法就是对每一个输入做一次卡拉茨验证,然后设立一个标记数组,由于输入不超过1000,所以可以设置标记数组flag[3001],在循环验证输入的时候,比如验证了2那么就对flag[2]++,这样只要进行一次遍历验证,那么就可以得到flag,查找flag中大于1的项就是重复验证的项,这样就只需要开销一个list和一个数组,这种方法在输入比较多的时候比较快速。

三个List的代码如下:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int rp = sc.nextInt();
        int numin;
        int num;
        List list = new ArrayList();
        List copylist = new ArrayList();
        List specillist = new ArrayList();
        for(int i=0; i=0; i--){
            if(i == specillist.size()-1)
                System.out.print(specillist.get(i));
            else
                System.out.print(" "+specillist.get(i));
        }
    }
    public static boolean ifSpecil(List copylist, int num){
        boolean flag = false;
        Integer testnum;
        for(int i=0; i1&&!(testnum.equals(num))){
                if(testnum%2 == 0){
                testnum = testnum/2;
                if(testnum == num)
                    flag = true;
                }
            else{
                testnum = (3*testnum+1)/2;
                if(testnum == num){
                    flag = true;
                    
                }
            }
            }
        }
        return flag;
    }
}

1006. 换个格式输出整数 (15)

让我们用字母B来表示“百”、字母S表示“十”,用“12...n”来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数。例如234应该被输出为BBSSS1234,因为它有2个“百”、3个“十”、以及个位的4。

 

输入格式:每个测试输入包含1个测试用例,给出正整数n(<1000)。

 

输出格式:每个测试用例的输出占一行,用规定的格式输出n。

 

输入样例1:

234

输出样例1:

BBSSS1234

输入样例2:

23

输出样例2:

SS123

这道题比较简单,代码如下

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int numb = num/100;
        num = num%100;
        int nums = num/10;
        int numg = num%10;
        String output = new String();
        while(numb > 0){
            output += "B";
            numb--;
        }
        while(nums > 0){
            output += "S";
            nums--;
        }
        for(int i=1; i

1007. 素数对猜想 (20)

让我们定义 dn 为:dn = pn+1 - pn,其中 pi 是第i个素数。显然有 d1=1 且对于n>1有 dn 是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N (< 105),请计算不超过N的满足猜想的素数对的个数。

 

输入格式:每个测试输入包含1个测试用例,给出正整数N。

 

输出格式:每个测试用例的输出占一行,不超过N的满足猜想的素数对的个数。

 

输入样例:

20

输出样例:

4

这个题目需要注意的是

1.不超过N的素数对,那么对于N是偶数和基数就要分开处理了

2.判断素数的时候for(int i=2;i

代码如下:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int pairnum = 0;
        int up = (num%2 == 1)? num/2:num/2-1;
        for(int i=1; i<=up; i++){
            if(isPrime(2*i-1)&&isPrime(2*i+1))
                pairnum++;
        }
        System.out.println(pairnum);
    }
    public static boolean isPrime(int num){
        if(num <= 2)
            return false;
        for(int i=2; i

1008. 数组元素循环右移问题 (20)

一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0A1……AN-1)变换为(AN-M …… AN-1 A0 A1……AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

 

输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100)、M(M>=0);第2行输入N个整数,之间用空格分隔。

 

输出格式:在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

 

输入样例:

6 2

1 2 3 4 5 6

输出样例:

5 6 1 2 3 4

这个题目说是不允许使用另外数组的前提下,当然如果使用另外的数组当然可以通过提交,因为测试用例测试不出来你是否使用了另外的数组,当然作为练习阶段当然还是不适用另外的数组比较好,其实实现起来也比较容易,因为N<=100,所以只要声明一个200的数组就,就可以把数组先整体后移动,再把后面的移上来就好了。代码如下所示:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    private int[] a;
    private int N;
    private int M;
 
    public Main(int[]a, int N, int M){
        this.a = a;
        this.N = N;
        this.M = M;
    }
    public  void cycleMove(){
        for(int i=N-1; i>=0; i--){
            a[i+M] = a[i];
        }
        for(int i=0; i

1009. 说反话 (20)

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

 

输入格式:测试输入包含一个测试用例,在一行内给出总长度不超过80的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用1个空格分开,输入保证句子末尾没有多余的空格。

 

输出格式:每个测试用例的输出占一行,输出倒序后的句子。

 

输入样例:

Hello World Here I Come

输出样例:

Come I Here World Hello

这个题目很简单没什么好说的,实现方法也很多,代码如下:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
   public static void main(String args[]){
       Scanner sc = new Scanner(System.in);
       String str = sc.nextLine();
       String[] strarr = str.split(" ");
       for(int i=strarr.length-1; i>=0; i--){
           if(i==strarr.length-1)
               System.out.print(strarr[i]);
           else
               System.out.print(" "+strarr[i]);
       }
   } 
}

1010. 一元多项式求导 (25)

设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为n*xn-1。)

 

输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

 

输出格式:以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是0,但是表示为“0 0”。

 

输入样例:

3 4 -5 2 6 1 -2 0

输出样例:

12 3 -10 1 6 0

这个题目很奇怪,因为其实题目已经给你规定好输入格式了非零项的系数和指数。如果n为洗漱,e为指数的话,保证了a大于0,只要考虑e大于零输出就好了,很奇怪的时候最后输入"0 0"的语句,理论上是永远达不到的,可能测试样对于0多项式的测试,采用了终止Scanner的方式,这样必须在后面加个判断,这个也是我网上找的处理方式,其实一开始我自己写的也一直过不了测试点,代码如下:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int a,b;
        boolean flag = false;
        while(sc.hasNext()){
            a = sc.nextInt();
            b = sc.nextInt();
            if(b>0)
                if(!flag){
                    System.out.print(a*b+" "+(b-1));
                    flag = true;
                }
                else{
                    System.out.print(" "+a*b+" "+(b-1));
                }
                    
        }
        if(!flag)
            System.out.print("0 0");
    }
}

1011. A+B和C (15)

给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。

输入格式:

 

输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。

 

输出格式:

 

对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号(从1开始)。

 

输入样例:

4

1 2 3

2 3 4

2147483647 0 2147483646

0 -2147483648 -2147483647

输出样例:

Case #1: false

Case #2: true

Case #3: true

Case #4: false

这个题目需要注意的是int类型的长度,java中int为32位所以会存在越界的现象,换成Long类型就没有问题了,代码如下:

import java.util.*;
/**
 *
 * @author zjb
 */
public class Main {
    public static void main(String[] args){
        //System.out.print(Integer.SIZE);
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        sc.nextLine();
        List list = new ArrayList();
        for(int i=0; i C)
                System.out.println("Case #"+(i+1)+": true");
            else
                System.out.println("Case #"+(i+1)+": false");
        }
    }
}















你可能感兴趣的:(Java,算法和数据结构,Java,上机题,算法,数据结构,PAT)