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

来源:互联网 发布:unity3d树木高模 编辑:程序博客网 时间:2024/06/05 01:54

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<numString.length(); i++){            num = Integer.parseInt(numString.substring(i,i+1));            sum += num;        }        changenum(sum);    }    public static void changenum(int num){       //System.out.println(num);       Stack<Integer> 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<num; i++){            int numa = 0;            int nump = 0;            int numt = 0;            boolean flag = false;            String str = sc.next();            for(int j=0; j<str.length(); j++){                char ch = str.charAt(j);                                if(ch == 'A')                    numa++;                else if(ch == 'P')                    nump++;                else if(ch == 'T')                    numt++;                else{                    flag = false;                    break;                }                   }              if(numa>=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<String> studentList = new ArrayList();        List<Integer> studentscore = new ArrayList();        for(int i=0; i<rp; i++){            studentInfo = sc.nextLine();            studentList.add(studentInfo);            //System.out.println(studentInfo);        }        if(rp == 1){            String[] output = studentList.get(0).split(" ");            System.out.println(output[0]+" "+output[1]);            System.out.println(output[0]+" "+output[1]);        }        else{            for(int i=0; i<studentList.size(); i++){                String[] arr = studentList.get(i).split(" ");                studentscore.add(Integer.parseInt(arr[2]));            }            Collections.sort(studentscore);            Integer min = studentscore.get(0);            Integer max = studentscore.get(studentscore.size()-1);            String[] minString = new String[2];            String[] maxString = new String[2];            for(int i=0; i<studentList.size(); i++){                String[] arr = studentList.get(i).split(" ");                if(min.equals(Integer.parseInt(arr[2]))){                    minString[0] = arr[0];                    minString[1] = arr[1];                }                if(max.equals(Integer.parseInt(arr[2]))){                    maxString[0] = arr[0];                    maxString[1] = arr[1];                }                            }            //String[] arr = maxString.split(" ");            System.out.println(maxString[0]+" "+maxString[1]);            //arr = minString.split(" ");            System.out.println(minString[0]+" "+minString[1]);                    }            }}

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<n<=100)的值,数字间用空格隔开。

 

输出格式:每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用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<Integer> list = new ArrayList();        List<Integer> copylist = new ArrayList();        List<Integer> specillist = new ArrayList();        for(int i=0; i<rp; i++){            numin = sc.nextInt();            list.add(numin);            copylist.add(numin);        }        //copylist = list;        Iterator it = list.iterator();              while(it.hasNext()){            num = (Integer)it.next();          //  System.out.println(num+"++");            if(!ifSpecil(copylist,num)){                specillist.add(num);               // System.out.println(num);            }        }       // B1005CMP cmp =  new B1005CMP();        Collections.sort(specillist);        for(int i=specillist.size()-1; 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; i<copylist.size(); i++){            testnum = (Integer)copylist.get(i);            //System.out.println(testnum);            while(testnum>1&&!(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<numg+1; i++){            output += i;        }        System.out.println(output);                        }}

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<Math.sqrt(num)+1; i++)只要整除num的开放加1就可以判断是不是素数,如果从2到nun-1的话,很可能超时间。

代码如下:

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<Math.sqrt(num)+1; i++){            if(num%i == 0)                return false;        }        return true;    }}

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<M; i++){            a[i] = a[N+i];        }    }        public  void display(){        for(int i=0; i<N; i++){           // System.out.println("+++++++++");            if(i == 0)                System.out.print(a[i]);            else                System.out.print(" "+a[i]);        }    }    public static void main(String args[]){        Scanner sc = new Scanner(System.in);        int N = sc.nextInt();        int M = sc.nextInt();        M = M%N;        int[] a =  new int[200];         for(int i=0; i<N; i++){            a[i] = sc.nextInt();        }       // System.out.println("+++++++++");        Main my = new Main(a,N,M);       // my.display();        my.cycleMove();        my.display();    }}

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<String> list = new ArrayList();        for(int i=0; i<T; i++){            list.add(sc.nextLine());        }        for(int i=0; i<T; i++){            String[] strarr = list.get(i).split(" ");            long A = Long.parseLong(strarr[0]);            long B = Long.parseLong(strarr[1]);            long C = Long.parseLong(strarr[2]);            //System.out.print(A+" "+B+" "+C+" ");            if(A+B > C)                System.out.println("Case #"+(i+1)+": true");            else                System.out.println("Case #"+(i+1)+": false");        }    }}















2 0
原创粉丝点击