本文為本人對PAT-B的簡要解析,盡可能用易于理解的方法與簡單的代碼,畢竟是這是算法測試而不是語法難度比拼。
1001.害死人不償命的(3n+1)猜想 (15)
卡拉茲(Callatz)猜想:
對任何一個自然數n,如果它是偶數,那么把它砍掉一半;如果它是奇數,那么把(3n+1)砍掉一半。這樣一直反復砍下去,最后一定在某一步得到n=1。卡拉茲在1950年的世界數學家大會上公布了這個猜想,傳說當時耶魯大學師生齊動員,拼命想證明這個貌似很傻很天真的命題,結果鬧得學生們無心學業,一心只證(3n+1),以至于有人說這是一個陰謀,卡拉茲是在蓄意延緩美國數學界教學與科研的進展……
我們今天的題目不是證明卡拉茲猜想,而是對給定的任一不超過1000的正整數n,簡單地數一下,需要多少步(砍幾下)才能得到n=1?
輸入格式:每個測試輸入包含1個測試用例,即給出自然數n的值。
輸出格式:輸出從n計算到1需要的步數。
//用遞歸的方法
#include <iostream>
using namespace std;
void Callatz(int n,int i){
if(n==1){
cout<<i;
}
else if(n%2==0){
i++;
n=n/2;
Callatz(n,i);
}
else{
i++;
n=(3*n+1)/2;
Callatz(n,i);
}
}
int main(){
int n,i=0;
cin>>n;
Callatz(n,i);
return 0;
}
1002.寫出這個數 (20)
讀入一個自然數n,計算其各位數字之和,用漢語拼音寫出和的每一位數字。
輸入格式:每個測試輸入包含1個測試用例,即給出自然數n的值。這里保證n小于 10^100。
輸出格式:在一行內輸出n的各位數字之和的每一位,拼音數字間有1 空格,但一行中最后一個拼音數字后沒有空格。
輸入樣例:
1234567890987654321123456789
輸出樣例:
yi san wu
#include <iostream>
#include <string.h>
using namespace std;
void print(int n){
const char *num[] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
if(n/10!=0) {
print(n/10);
cout<<" "<<num[n%10];
}else{
cout<<num[n%10];
}
}
int main() {
char str[101];
cin>>str;
int i,sum = 0;
for (i = 0; i < (int)strlen(str); i++) {
if (str[i]>='0' && str[i]<='9') {
sum += str[i] - '0';
}else{
break;
}
}
if (i==(int)strlen(str)) {
print(sum);
}else{
return 0;
}
return 0;
}
1003.我要通過!(20)
“答案正確”是自動判題系統給出的最令人歡喜的回復。本題屬于PAT的“答案正確”大派送 —— 只要讀入的字符串滿足下列條件,系統就輸出“答案正確”,否則輸出“答案錯誤”。
得到“答案正確”的條件是:
- 字符串中必須僅有P, A, T這三種字符,不可以包含其它字符;
- 任意形如 xPATx 的字符串都可以獲得“答案正確”,其中 x 或者是空字符串,或者是僅由字母 A 組成的字符串;
- 如果 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
這一題對于題目條件的理解很有難度,即第三條是建立于第二條的推廣,要歸納出滿足2、3條件的算式。
歸納三個條件得:
1.字符串僅有pat這三種字符
2.p、t各只有一個
3.p的位置在t前
4.p前a個數乘pt間a個數 等于 t后a個數
因此只需要對p\a\t計數并記住位置即可。
#include <iostream>
#include<string.h>
using namespace std;
int main(){
int n,len;//字符串個數與臨時長度
int p,a,t,p_pos,t_pos;//p、a、t分別為計數,p_pos與t_pos是p、t的位置(pt只能有一個)
char str[100];
cin>>n;
while(n--){//運行n次,即讀取n個字符串
cin>>str;
p = a = t = p_pos = t_pos = 0;//對每一個字符串初始化
len = strlen(str);
for(int i = 0;i < len;i++){
if(str[i] == 'P'){
p++;
p_pos = i;
}
else if(str[i] == 'A'){
a++;
}
else if(str[i] == 'T'){
t++;
t_pos = i;
}
}
if(p+a+t != len || p > 1 || t > 1 || p_pos >= t_pos - 1 || p_pos * (t_pos - p_pos - 1) != len - t_pos - 1)
cout<<"NO\n";
//輸出no的情況:
//1.字符串并非全是pat這三個字符
//2.p、t任一個多于一個
//3.p的位置在t后
//4.p前a個數乘pt間a個數 不等于 t后a個數
else cout<<"YES\n";//滿足所有條件即為yes
}
return 0;
}
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
#include <iostream>
using namespace std;
struct student{
char name[11];
char num[11];
int grade;
};
int main(){
int n,i;//學生個數
cin>>n;
student stu[n];
student smin={"","",101};//最大設為101比較好,也可以大于101
student smax={"","",-1};//最小為-1,0的話學生成績也可能是0就存不進去了
for(i=0;i<n;i++){//邊讀邊判斷,分開的話會判錯,不知道為什么
cin>>stu[i].name>>stu[i].num>>stu[i].grade;
if(stu[i].grade>smax.grade){
smax=stu[i];
}
if(stu[i].grade<smin.grade){
smin=stu[i];
}
}
cout<<smax.name<<" "<<smax.num<<endl;
cout<<smin.name<<" "<<smin.num;
return 0;
}
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
超級簡單的一道題。。。既然不超過三位數那么分別按位輸出一下就行
#include <iostream>
using namespace std;
void print(int n){
int i;
for(i=0;i<(n/100)%10;i++){
cout<<"B";
}
for(i=0;i<(n/10)%10;i++){
cout<<"S";
}
for(i=1;i<=n%10;i++){
cout<<i;
}
}
int main()
{
int n;
cin>>n;
print(n);
}