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的代码如下: 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 这道题比较简单,代码如下 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 代码如下: 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的数组就,就可以把数组先整体后移动,再把后面的移上来就好了。代码如下所示: 1009. 说反话 (20) 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。 输入格式:测试输入包含一个测试用例,在一行内给出总长度不超过80的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用1个空格分开,输入保证句子末尾没有多余的空格。 输出格式:每个测试用例的输出占一行,输出倒序后的句子。 输入样例: Hello World Here I Come 输出样例: Come I Here World Hello 这个题目很简单没什么好说的,实现方法也很多,代码如下: 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的方式,这样必须在后面加个判断,这个也是我网上找的处理方式,其实一开始我自己写的也一直过不了测试点,代码如下: 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[]){
Scanner sc = new Scanner(System.in);
int rp = sc.nextInt();
int numin;
int num;
List
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
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
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
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]);
}
}
}
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");
}
}
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