PAT_B 刷题总结
PAT_B_1001 害死人不偿命的(3n+1)猜想
题目描述:
卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展…… 我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1? 输入格式: 每个测试输入包含 1 个测试用例,即给出正整数 n 的值。 输出格式: 输出从 n 计算到 1 需要的步数。 输入样例: 3 输出样例: 5
AC代码:
1 // Guess Number from 3*n+1 -> 1 2 3 # include <stdio.h> 4 5 int main(void) 6 { 7 int n; // 输入一个整数 8 int temp = 0; // 记录 n 转化到 1 总共进行了多少次的运算 9 10 scanf("%d",&n); 11 12 while (n != 1) 13 { 14 if (n%2 == 0) 15 { 16 n = n/2; 17 } 18 else 19 { 20 n = (3*n+1)/2; 21 } 22 temp++; 23 } 24 25 printf("%d\n",temp); 26 27 return 0; 28 }
Python代码:
n = int(input()) temp = 0 while n!=1: if n%2==0: n /= 2 else: n = 3*n+1 n /= 2 temp = temp + 1 print(temp)
PAT_B_1002 写出这个数
题目描述:
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10100。 输出格式: 在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。 输入样例: 1234567890987654321123456789 输出样例: yi san wu
AC代码:
// Get the number to Chinese // 计算给出的数字的和并输出结果的汉语拼音 # include <stdio.h> int main(void) { // 记录大型整数的数组 char NUM[1000]; // 用一个整数记录各位之和 int sum = 0; // 表示每一位对应的汉语拼音 // 这里用 switch 函数输出结果即可 // 用一个数组来表示分解后的整数 int flag[4] = {-1, -1, -1, -1}; int i = 0; scanf("%s",NUM); // 用一个字符串记录大型整数 // 把字符串转化为整数(实际不用操作) 并求和 while (NUM[i] != '\0') { sum += NUM[i] - '0'; i++; } // 把sum转化为汉语拼音 // 从最高位向下依次读取 // 此处必须使用的是sum 的位数计算 而不是原来大型整数的位数i // 计算sum 的每一位 (用一个数组来表示) // 如123 在数组中表示为 3 2 1 -1 i = 0; while (sum >= 10) { flag[i] = sum%10; sum = sum/10; i++; } sum = sum - (sum/10); flag[i] = sum; // printf("%d\n",i); // printf("%d %d %d %d",flag[0], flag[1], flag[2], flag[3]); for (i=3; i>=0; i--) { if (flag[i] != -1) { // 注意 此处的flag[i] 是整数类型 不能用符号表示 switch (flag[i]) { case 1: printf("yi");break; case 2: printf("er");break; case 3: printf("san");break; case 4: printf("si");break; case 5: printf("wu");break; case 6: printf("liu");break; case 7: printf("qi");break; case 8: printf("ba");break; case 9: printf("jiu");break; case 0: printf("ling");break; default: break; } if (i>0) printf(" "); } } return 0; }
PAT_B_1003 我要通过!
题目描述:
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 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
AC代码:
// Auto_PAT // “答案正确”的条件是: // 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; // 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串; // 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。 # include <stdio.h> # include <stdlib.h> // 用链表来实现字符的存储 typedef struct ch { char val[101]; struct ch * next; }CH, * PCH; int main(void) { int n; PCH pHead, pTail; // 指针类型 (头指针)(尾指针) PCH pNODE; int i, j; int P,T; int count1, count2, count3; char temp; count1 = count2 = count3 = 0; P = T = 0; int flag = -1; pHead = (PCH)malloc(sizeof(CH)); pTail = pHead; // 初始化链表,分配内存 scanf("%d",&n); for (i=0; i<n; i++) { PCH pNode = (PCH)malloc(sizeof(CH)); pTail->next = pNode; pNode->next = NULL; pTail = pNode; } // 输入字符 pNODE = pHead->next; for (i=0; i<n; i++) { scanf("%s",pNODE->val); pNODE = pNODE->next; } // 下面对输入的内容进行判断 pNODE = pHead->next; for (i=0; i<n; i++) { count1 = count2 = count3 = 0; P = 0; T = 0; j = 0; while(pNODE->val[j] != '\0') { // printf("=================================\n"); temp = pNODE->val[j]; if(temp=='P'||temp=='A'|| temp=='T') { // 计算 PT 前面的 中间的 后面的A 的个数 if (temp == 'P') P++; // printf("P === %d \n",P); if (temp == 'T') T++; if (P>1 || T>1) { flag = 0; break; } if (temp=='T' && P==0) { flag = 0; break; } // P 前面 if (P==0) { if(temp == 'A') count1++; } // pT 之间 if (P==1 && T==0) { if(temp == 'A') count2++; } // T 后面 if (P==1 && T==1) { if(temp == 'A') count3++; } if (count1*count2 == count3) flag = 1; else flag = 0; if (count2 == 0) flag = 0; } else { flag = 0; break; } j++; } if (P==0 || T==0) { flag = 0; } // printf("flag ==== %d\n",flag); if (flag == 0) printf("NO\n"); else printf("YES\n"); pNODE = pNODE->next; } return 0; }
PAT_B_1004 成绩排名
题目描述:
读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。 输入格式: 每个测试输入包含 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
AC代码:
// PAT_1 成绩排名 # include <stdio.h> # include <stdlib.h> // 将学生结构体定义为指针类型 typedef struct student { char Name[11]; char Number[11]; int Score; }*Student; int main(void) { int n; // 代表学生人数 scanf("%d",&n); Student S; // 指针类型 int i; int flag_min, flag_max; // 仅用下标代表最大最小值项 // 动态分配内存? // ************************************************* // 此处存在很大问题 S = (Student)malloc(n*40*sizeof(Student)); // 判断内存是否分配成功 if (NULL == S) { // 内存分配失败! exit(-1); } for (i=0; i<n; i++) { scanf("%s%s %d",S[i].Name, S[i].Number, &S[i].Score); } // 注:在输入字符串的时候可以考虑以下输入方法 // scanf ("%s%d %c%s", stu[i].name, &stu[i].age, &stu[i].sex, stu[i].num); // %c前面要加空格, 不然输入时会将空格赋给%c // 对学生成绩进行排名 // 找出最小值 flag_min = 0; flag_max = 0; for (i=1; i<n; i++) { // 比较完成绩移动谁? if (S[flag_min].Score > S[i].Score) flag_min = i; if (S[flag_max].Score < S[i].Score) flag_max = i; } printf("%s %s\n",S[flag_max].Name,S[flag_max].Number); printf("%s %s\n",S[flag_min].Name,S[flag_min].Number); free(S); // 释放指针 return 0; }
PAT_B_1005 继续(3n+1)猜想
题目描述:
卡拉兹(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
主要思想:
利用一个数组,初始置零,用于标记某个数字是否为关键数; 并在运算过程中添加一个计数器,记录关键数的个数; 最后,倒序遍历数组,如果标记为1则打印输出关键字。
本人代码:
// Guess Number from 3*n+1 -> 1 // Go ahead // 这种解法(22/25) 最后一个测试点过不去 // 上述问题已经解决,在代码 47行,48行给出了部分解释 /* 当我们验证卡拉兹猜想的时候,为了避免重复计算, 可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候, 我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候, 就可以直接判定卡拉兹猜想的真伪,而不需要重复计算, 因为这 4 个数已经在验证3的时候遇到过了, 我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”, 如果 n 不能被数列中的其他数字所覆盖。 现在给定一系列待验证的数字,我们只需要验证其中的几个关键数, 就可以不必再重复验证余下的数字。 你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。 */ # include <stdio.h> int main(void) { int k; // 输入一个整数 k<100 int n, temp; int i; int table[101] = {0}; // 记录数据是否出现 (不用再单独排序) // 定义为300 不会出现数组越界的情况 int val = 0; // 记录 最终table 中有多少个不为零的数 scanf("%d",&k); for (i=0; i<k; i++) { scanf("%d",&temp); table[temp] = 1; } for (i=1; i<=100; i++) { // 如果此数字在table中出现过,则进行运算 if (1 == table[i]) { n = i; while(n>1) { if (n%2 == 0) n = n/2; else n = ((3*n)+1)/2; // 如果此处写 n = 3*n+1 则会在最后一个测试点无法通过,没有仔细的看数字猜想过程,(3*n+1)/2 // 判断计算过程中的数是否在输入数组中出现 // 注:在提交过程中 如果直接判断 table[n] (n==100)可能会出现数组越界的情况 if (n<=100 && n>=2) { table[n] = 0; } } } } // 输出table中不为0 的下标的个数 for (i=100; i>=1; i--) { if (1 == table[i]) val++; } for (i=100; i>=1; i--) { if (1==table[i]) { printf("%d",i); val--; if (val != 0) printf(" "); } } return 0; }
PAT_B_1006 换个格式输出整数
题目描述:
让我们用字母 B 来表示“百”、字母 S 表示“十”,用 12...n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234,因为它有 2 个“百”、3 个“十”、以及个位的 4。 输入格式: 每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。 输出格式: 每个测试用例的输出占一行,用规定的格式输出 n。 输入样例 1: 234 输出样例 1: BBSSS1234 输入样例 2: 23 输出样例 2: SS123
AC代码:
# include <stdio.h> int main(void) { int val; // 记录输入的数据 scanf("%d",&val); int Hun = 0, Ten = 0, Num = 0; int i; if (val >= 100) { Hun = val/100; Ten = (val - Hun*100)/10; Num = val % 10; } else if (val >= 10) { Ten = val/10; Num = val%10; } else Num = val; for (i=0; i<Hun; i++) { printf("B"); } for (i=0; i<Ten; i++) { printf("S"); } for (i=0; i<Num; i++) { printf("%d",i+1); } return 0; }
python代码:
# 换个格式输出 num = int(input()) # 输出百位 H = int(num/100) num %= 100 for i in range(H): print("B", end="") # 控制不换行输出 # 输出十位 T = int(num/10) num %= 10 for i in range(T): print("S", end="") # 控制不换行输出 # 输出个位 for i in range(num): print(i+1, end="") # 控制不换行输出
改进后代码:
// 换个格式输出整数 (15 分) # include <stdio.h> int main(void) { int n, i; // 记录输入的数据 scanf("%d",&n); int Hun = 0, Ten = 0, Num = 0; Hun = n/100; n %= 100; for (i=0; i<Hun; i++) printf("B"); Ten = n/10; n %= 10; for (i=0; i<Ten; i++) printf("S"); Num = n; for (i=0; i<Num; i++) printf("%d",i+1); return 0; }
PAT_B_1007 素数对猜想
题目描述:
让我们定义dn 为:dn =pn+1 −pn ,其中pi 是第i个素数。 显然有d1 =1,且对于n>1有dn 是偶数。 “素数对猜想”认为“存在无穷多对相邻且差为2的素数”。 现给定任意正整数N(<105 ),请计算不超过N的满足猜想的素数对的个数。 输入格式: 输入在一行给出正整数N。 输出格式: 在一行中输出不超过N的满足猜想的素数对的个数。 输入样例: 20 输出样例: 4
本人AC代码:
# include <stdio.h> # include <math.h> int Prime(int n); int main(void) { int n; int count = 0; scanf("%d",&n); for (int i=2; i<=n-2; i++) { if (Prime(i) && Prime(i+2)) count++; } printf("%d",count); return 0; } int Prime(int n) { int i = 2; for (i; i<=sqrt(n); i++) { if (n%i == 0) return 0; } return 1; }
PAT_B_1008 数组元素循环右移问题
题目描述:
一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0 A1 ⋯AN−1 )变换为(AN−M ⋯AN−1 A0 A1 ⋯AN−M−1 ) (最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法? 输入格式: 每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。 输出格式: 在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。 输入样例: 6 2 1 2 3 4 5 6 输出样例: 5 6 1 2 3 4
AC代码:
// 将数组右移两位 // 通过控制数组的下标来输出元素 # include <stdio.h> int main(void) { int n, temp; // n为输入的总长度,temp为需要移动的位数 int A[100]; int flag = 0; int i, k; scanf("%d %d",&n, &temp); temp = temp%n; // 输入数组元素 for (i=0; i<n; i++) { scanf("%d",&A[i]); } /* // 输出元素, 方法一 for (i=0; i<n; i++) { if (i<temp) flag = 1; else flag = 0; if (flag == 1) { k = n-temp+i; // 输出 5 6 } else { k = i-temp; // 输出 1 2 3 4 } printf("%d",A[k]); if (i+1 != n) { printf(" "); } } */ // 输出元素,方法二 for (i=0; i<n; i++) { k = (i+n-temp)%n; printf("%d",A[k]); if (i+1 != n) { printf(" "); } } return 0; }
PAT_B_1009 说反话
题目描述:(总结C语言字符串的用法)
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。 输出格式: 每个测试用例的输出占一行,输出倒序后的句子。 输入样例: Hello World Here I Come 输出样例: Come I Here World Hello
AC代码:
方法一:(改进版)
// 1009 说反话 (20 分) // 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。 // 时间 2019年7月15日 # include <stdio.h> # include <string.h> int main(void) { char S[100]; int tail, head; // 读入字符串 gets(S); int len = strlen(S); head = tail = len-1; for (int i=len-1; i>=0; i--) { if (S[i] == ' ' || i==0) { head = i; for (head; head<=tail;head++) { if (S[head] != ' ') printf("%c",S[head]); } tail = i; if (i != 0) printf(" "); } } return 0; }
方法二:(初级版)(我已经不是当初写方法二时的我了,我也不知道咋想的 0.0)
// 1009 说反话 (20 分) // 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。 // 时间 2019年2月6日 # include <stdio.h> # include <stdlib.h> int main(void) { char S[100]; char ch; int i, j; int n; // 记录字符串的长度 int new_head, head, tail; for (i=0; i<100; i++) { S[i] = getchar(); if (S[i] == 10) // 换行符的ASCII码值为 10 当遇到就停止输入 break; } n = i; new_head = 0; for (i=0; i<n; i++) { tail = i; // 处理出去最后一组之外的所有字符 if (S[i] == 32) { tail--; head = new_head; for (j=head; j<tail; j++) { ch = S[head]; S[head] = S[tail]; S[tail] = ch; head++; tail--; if (head>=tail) break; } new_head = i+1; } // 处理最后一个单词 if (i == n-1) { tail = n-1; head = new_head; for (j=head; j<tail; j++) { ch = S[head]; S[head] = S[tail]; S[tail] = ch; head++; tail--; if (head>=tail) break; } } } for (i=n-1; i>=0; i--) { printf("%c",S[i]); } return 0; }
PAT_B_1010 一元多项式求导
题目描述:
设计函数求一元多项式的导数。 输入格式: 以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。 输出格式: 以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0 0。 输入样例: 3 4 -5 2 6 1 -2 0 输出样例: 12 3 -10 1 6 0
AC代码:
// 对多项式求导数 # include <stdio.h> int main(void) { // 记录系数以及多项式的次数 int A[1000]={0}; // 记录系数 int B[1000]={0}; // 记录多项式的次数 int i, flag=0; int n; // 输入系数以及次数 for (i=0; flag==0; i++) { scanf("%d",&A[i]); scanf("%d",&B[i]); if (getchar() == 10) flag=1; } n = (i--); // 输出已输入的多项式 // for (i=0; i<n; i++) // { // printf("%d %d \n",A[i],B[i]); // } // 依次对每一项进行降次求导 for (i=0; i<n; i++) { A[i] = B[i] * A[i]; if (0 < B[i]) { B[i]--; } else { n--; break; } } for (i=0; i<n-1; i++) { printf("%d %d ",A[i],B[i]); } printf("%d %d",A[n-1],B[n-1]); return 0; }
PAT_B_1011 A+B 和 C
题目描述:
给定区间 [−2^1 ,2^31 ] 内的 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
AC代码:
// 比较大小 # include <stdio.h> int main(void) { long long A[10]; long long B[10]; long long C[10]; int i; int n; // 输入数据 scanf("%d",&n); for (i=0; i<n; i++) { scanf("%ld",&A[i]); scanf("%ld",&B[i]); scanf("%ld",&C[i]); } // 比较大小 for (i=0; i<n; i++) { printf("Case #%d: ",i+1); if (A[i]+B[i] > C[i]) { printf("true\n"); } else { printf("false\n"); } } return 0; }
PAT_B_1012 数字分类
题目描述:
给定一系列正整数,请按要求对数字进行分类,并输出以下 5 个数字: A1 = 能被 5 整除的数字中所有偶数的和; A2 = 将被 5 除后余 1 的数字按给出顺序进行交错求和,即计算 n1 −n2 +n3 −n4 ⋯; A3 = 被 5 除后余 2 的数字的个数; A4 = 被 5 除后余 3 的数字的平均数,精确到小数点后 1 位; A5 = 被 5 除后余 4 的数字中最大数字。 输入格式: 每个输入包含 1 个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N,随后给出 N 个不超过 1000 的待分类的正整数。数字间以空格分隔。 输出格式: 对给定的 N 个正整数,按题目要求计算 A1 ~A5 并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。 若其中某一类数字不存在,则在相应位置输出 N。 输入样例 1: 13 1 2 3 4 5 6 7 8 9 10 20 16 18 输出样例 1: 30 11 2 9.7 9 输入样例 2: 8 1 2 4 5 6 7 9 16 输出样例 2: N 11 2 N 9
AC代码:(有待改进)
// 分类 # include <stdio.h> # include <stdlib.h> int main(void) { int N; int A1 = 0, A2 = 0, A3 = 0, A5 = 0; float A4 = 0.0; int flag_1=0, flag_2=0, flag_3=0, flag_4=0, flag_5=0; int *A; int i; int temp; // 输入数据 //*********************** // 注:int mian 出错 [Error] ld returned 1 exit status scanf("%d",&N); A = (int *)malloc(N*(sizeof(int))); for (i=0; i<N; i++) { scanf("%d",&A[i]); } // 对数据进行分类 for (i=0; i<N; i++) { temp = A[i]%5; switch(temp) { case 0: if (A[i]%10 == 0) { flag_1++; A1 += A[i]; } break; case 1: { flag_2++; if (flag_2%2 == 1) { A2+=A[i]; } else { A2-=A[i]; } } break; case 2: flag_3++;break; case 3: { flag_4++; A4 += A[i]; } break; case 4: { flag_5++; A5 = A5>A[i]?A5:A[i]; } break; default:break; } } A4 = A4/flag_4; A3 = flag_3; if (flag_1 == 0) { printf("N "); } else printf("%d ",A1); if (flag_2 == 0) { printf("N "); } else printf("%d ",A2); if (flag_3 == 0) { printf("N "); } else printf("%d ",A3); if (flag_4 == 0) { printf("N "); } else printf("%0.1f ",A4); if (flag_5 == 0) { printf("N"); } else printf("%d",A5); return 0; }
PAT_B_1013 数素数
题目描述:
令 Pi 表示第 i 个素数。现任给两个正整数 M≤N≤10^4 ,请输出 PM 到 PN 的所有素数。 输入格式: 输入在一行中给出 M 和 N,其间以空格分隔。 输出格式: 输出从 PM 到 PN 的所有素数,每 10 个数字占 1 行,其间以空格分隔,但行末不得有多余空格。 输入样例: 5 27 输出样例: 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103
AC代码:
// 输出第 M 到 第 N 个 素数 # include <stdio.h> # include <math.h> int Is_Prime(int); int main(void) { int i; int N1, N2; int n = 105000; int flag = 0; int flag_ch = 0; scanf("%d %d",&N1,&N2); for (i=1; i<n; i++) { if (Is_Prime(i)) { flag++; if (flag>N1 && flag<=N2+1) { flag_ch++; printf("%d",i); if (flag_ch<10 && flag!=N2+1) { printf(" "); } else { printf("\n"); flag_ch -= 10; } } } } return 0; } int Is_Prime(int n) { int i = 1; int temp = sqrt(n); for (i=2; i<=temp; i++) { if (n%i == 0) return 0; } return 1; }
PAT_B_1014 福尔摩斯的约会
题目描述:
大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm。大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母 D,代表星期四;第 2 对相同的字符是 E ,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母 A 到 N 表示);后面两字符串第 1 对相同的英文字母 s 出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。 输入格式: 输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。 输出格式: 在一行中输出约会的时间,格式为 DAY HH:MM,其中 DAY 是某星期的 3 字符缩写,即 MON 表示星期一,TUE 表示星期二,WED 表示星期三,THU 表示星期四,FRI 表示星期五,SAT 表示星期六,SUN 表示星期日。题目输入保证每个测试存在唯一解。 输入样例: 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm 输出样例: THU 14:04
AC代码:(有待改进)
// 福尔摩斯的约会 # include <stdio.h> # include <stdlib.h> int main(void) { // 输入四组字符串 char CH1[100]; char CH2[100]; char CH3[100]; char CH4[100]; int i=0, j=0; char ch[2]={'0','0'}; int flag=0, min=0; int day, hour; // 输入 scanf("%s",CH1); scanf("%s",CH2); scanf("%s",CH3); scanf("%s",CH4); // 计算day HH while (CH1[i]!='\0' && CH2[i]!='\0') { // 表示第一个大写字母一样 if (flag == 0) { if (CH1[i]>='A'&&CH1[i]<='G') { if (CH1[i]==CH2[i]) { ch[flag]=CH1[i]; flag++; } } } else { if ((CH1[i]>='a'&&CH1[i]<='n') || (CH1[i]>='A'&&CH1[i]<='N') || (CH1[i]>='0'&&CH1[i]<='9')) { if (CH1[i]==CH2[i]) { ch[flag]=CH1[i]; flag++; } } } i++; if (flag == 2) break; } // 计算DAY if (ch[0]>='a'&&ch[0]<='z') { day = ch[0] - 'a' + 1; } else day = ch[0] - 'A' + 1; // 计算HH if (ch[1]>='A'&&ch[1]<='N') { hour = ch[1] - 'A' + 10; } else if (ch[1]>='0'&&ch[1]<='9') hour = ch[1] - '0'; // 计算MIN while (CH3[j]!='\0' && CH4[j]!='\0') { if ((CH3[j]>='a'&&CH3[j]<='z') || (CH3[j]>='A'&&CH3[j]<='Z')) if (CH3[j]==CH4[j]) { break; } j++; } min = j%61; // printf("ch0 %c ch1 %c \n",ch[0], ch[1]); // printf("DAY %d HH %d MIN %d \n",day, hour, min); // 输出DAY switch(day) { case 1: printf("MON ");break; case 2: printf("TUE ");break; case 3: printf("WED ");break; case 4: printf("THU ");break; case 5: printf("FRI ");break; case 6: printf("SAT ");break; case 7: printf("SUN ");break; default:break; } // 输出HH if (hour>=10) printf("%d:",hour); else { printf("0"); printf("%d:",hour); } // 输出 MIN if (min>=10) printf("%d",min); else { printf("0"); printf("%d",min); } return 0; }
PAT_B_1015 德才论
题目描述:
宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。” 现给出一批考生的德才分数,请根据司马光的理论给出录取排名。 输入格式: 输入第一行给出 3 个正整数,分别为:N(≤10^5 ),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于 H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。 随后 N 行,每行给出一位考生的信息,包括:准考证号 德分 才分,其中准考证号为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。 输出格式: 输出第一行首先给出达到最低分数线的考生人数 M,随后 M 行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。 输入样例: 14 60 80 10000001 64 90 10000002 90 60 10000011 85 80 10000003 85 80 10000004 80 85 10000005 82 77 10000006 83 76 10000007 90 78 10000008 75 79 10000009 59 90 10000010 88 45 10000012 80 100 10000013 90 99 10000014 66 60 输出样例: 12 10000013 90 99 10000012 80 100 10000003 85 80 10000011 85 80 10000004 80 85 10000007 90 78 10000006 83 76 10000005 82 77 10000002 90 60 10000014 66 60 10000008 75 79 10000001 64 90
AC代码:(有待改进)
# include <stdio.h> # include <stdlib.h> int main(void) { // 定义学生人数,最低录取线,优先录取线 int N, L, H; int *Num, *Dem, *Skill, *Temp, *Sum, *Flag; int i, j; int N_Sum = 0; // 合格的总人数 int flag; scanf("%d%d%d",&N, &L, &H); // 动态分配内存,并输入考生信息 Num = (int *)malloc(N*(sizeof(int))); Dem = (int *)malloc(N*(sizeof(int))); Skill = (int *)malloc(N*(sizeof(int))); Sum = (int *)malloc(N*(sizeof(int))); Temp = (int *)malloc(N*(sizeof(int))); // 定义学生的档次 Flag = (int *)malloc(N*(sizeof(int))); // 标记学生序号 // 输入考生信息 for (i=0; i<N; i++) { scanf("%d",&Num[i]); scanf("%d",&Dem[i]); scanf("%d",&Skill[i]); Temp[i] = 0; Sum[i] = Dem[i] + Skill[i]; // 记录学生总分 Flag[i] = i; } // 判断分别属于哪一类 for (i=0; i<N; i++) { if (Dem[i]>=L && Skill[i]>=L) { Temp[i] = 1; // 表示可以录取 N_Sum++; if (Dem[i]>=H && Skill[i]>=H) { Temp[i] = 5; // 表示优先录取 才德全尽 } else if (Dem[i]>=H && Skill[i]<H) { Temp[i] = 3; // 德胜才 } else if (Dem[i]<H && Skill[i]<H && Dem[i]>=Skill[i]) { Temp[i] = 2; // 才德兼亡 } } else { Temp[i] = -1; // 表示学生不合格 } } // 去掉不合格人的信息 if (N_Sum == 0) { printf("%d\n",N_Sum); return 0; } for (i=0; i<=N_Sum; i++) { if (Temp[i] == -1) { for (j=i; j<=N_Sum; j++) { Num[j] = Num[j+1]; Dem[j] = Dem[j+1]; Skill[j] = Skill[j+1]; Sum[j] = Sum[j+1]; Temp[j] = Temp[j+1]; Flag[j] = Flag[j+1]; } i--; // 从此断点处重新检查,以免移动的是无效信息 } } // 分段排序 for (i=0; i<N_Sum; i++) { for (j=i+1; j<N_Sum; j++) { if (Sum[i]<Sum[j]) { flag = Flag[i] ; Flag[i] = Flag[j]; Flag[j] = flag; } else if(Sum[i] == Sum[j]) { if (Dem[i] < Dem[j]) { flag = Flag[i] ; Flag[i] = Flag[j]; Flag[j] = flag; } else if (Dem[i] == Dem[j]) { if (Num[i] > Num[j]) { flag = Flag[i] ; Flag[i] = Flag[j]; Flag[j] = flag; } } } } } // 调整所有学生顺序 for (i=0; i<N_Sum; i++) { for (j=i+1; j<N_Sum; j++) { if (Temp[i]<Temp[j]) { flag = Flag[i] ; Flag[i] = Flag[j]; Flag[j] = flag; } } } printf("%d\n",N_Sum); N = N_Sum; j=0; // 输出合格学生信息 while (j<N_Sum) { for (i=0; i<N; i++) { if (Flag[i] == j) { printf("%d ",Num[i]); printf("%d ",Dem[i]); printf("%d\n",Skill[i]); break; } } j++; } return 0; }
PAT_B_1016 部分A+B
题目描述:
正整数 A 的“DA (为 1 位整数)部分”定义为由 A 中所有 DA 组成的新整数 PA 。 例如:给定 A=3862767,DA =6,则 A 的“6 部分”PA 是 66,因为 A 中有 2 个 6。 现给定 A、DA 、B、DB ,请编写程序计算 PA +PB 。 输入格式: 输入在一行中依次给出 A、DA 、B、DB ,中间以空格分隔,其中 0<A,B<10^10 。 输出格式: 在一行中输出 PA +PB 的值。 输入样例 1: 3862767 6 13530293 3 输出样例 1: 399 输入样例 2: 3862767 1 13530293 8 输出样例 2: 0
AC代码:
// 1016 部分A+B (15 分) # include <stdio.h> int main(void) { char A[11], B[11]; int D_A, D_B, Sum; int N_A=0, N_B=0; // 构造新的 Pa Pb int L_A=0, L_B=0; // A B 的长度 int i=0; scanf("%s",A); scanf("%d",&D_A); scanf("%s",B); scanf("%d",&D_B); while(A[i] != '\0') { if ((A[i]-'0') == D_A) { L_A++; } i++; } i=0; while(B[i] != '\0') { if ((B[i]-'0') == D_B) { L_B++; } i++; } // 计算 D_A D_B for (i=0; i<L_A; i++) { N_A = (N_A*10+D_A); } for (i=0; i<L_B; i++) { N_B = (N_B*10+D_B); } Sum = N_A + N_B; printf("%d",Sum); return 0; }
PAT_B_1017 A除以B
题目描述:
本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。 输入格式: 输入在一行中依次给出 A 和 B,中间以 1 空格分隔。 输出格式: 在一行中依次输出 Q 和 R,中间以 1 空格分隔。 输入样例: 123456789050987654321 7 输出样例: 17636684150141093474
本人AC代码:
// 1017 A除以B #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> int main(void) { char a[1000]; int b; int temp=0; int flag = 0; scanf("%s",a); scanf("%d",&b); int n = strlen(a); for(int i=0; i<n; i++) { temp = (a[i]-'0')+temp*10; if(temp>=b) { printf("%d",temp/b); flag = 1; } else if(flag) { printf("0"); } temp = temp%b; } if(flag==0) printf("0"); printf(" %d",temp); return 0; }
PAT_B_1018 锤子剪刀布
题目描述:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。 输入格式: 输入第 1 行给出正整数 N(≤10^5 ),即双方交锋的次数。随后 N 行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”,第 1 个字母代表甲方,第 2 个代表乙方,中间有 1 个空格。 输出格式: 输出第 1、2 行分别给出甲、乙的胜、平、负次数,数字间以 1 个空格分隔。第 3 行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有 1 个空格。如果解不唯一,则输出按字母序最小的解。 输入样例: 10 C J J B C B B B B C C C C B J B B C J J 输出样例: 5 3 2 2 3 5 B B
本人AC代码:
// PAT_1018_锤子剪刀布 # include <stdio.h> int win_lose(char A, char B) { // 平手 if (A==B) return 0; // 甲胜出 else if (A=='C'&&B=='J' || A=='J'&&B=='B' || A=='B'&&B=='C') return 1; // 乙胜出 else if (A=='J'&&B=='C' || A=='B'&&B=='J' || A=='C'&&B=='B') return -1; } int main(void) { int N; // 记录游戏次数 int flag; char ch1, ch2; int win=0, lose=0, draw=0; int A_C=0, A_J=0, A_B=0; int B_C=0, B_J=0, B_B=0; int Max_A=0,Max_B=0; scanf("%d",&N); getchar(); while(N--) { scanf("%c",&ch1); getchar(); scanf("%c",&ch2); getchar(); // 记录胜负平次数 flag = win_lose(ch1, ch2); if (flag == 0) draw++; // 甲胜出 else if (flag == 1) { win++; switch(ch1) { case 'B':A_B++;break; case 'J':A_J++;break; case 'C':A_C++;break; default:break; } } else if (flag == -1) { lose++; switch(ch2) { case 'B':B_B++;break; case 'J':B_J++;break; case 'C':B_C++;break; default:break; } } } printf("%d %d %d\n",win, draw, lose); printf("%d %d %d\n",lose, draw, win); Max_A = (A_C>A_J)?A_C:A_J; Max_A = (Max_A>A_B)?Max_A:A_B; Max_B = (B_C>B_J)?B_C:B_J; Max_B = (Max_B>B_B)?Max_B:B_B; if (Max_A == A_B) { printf("B "); } else if (Max_A == A_C) { printf("C "); } else if (Max_A == A_J) { printf("J "); } if (Max_B == B_B) { printf("B"); } else if (Max_B == B_C) { printf("C"); } else if (Max_B == B_J) { printf("J"); } return 0; }
PAT_B_1019 数字黑洞
题目描述:
给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的 6174,这个神奇的数字也叫 Kaprekar 常数。 例如,我们从6767开始,将得到 7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 7641 - 1467 = 6174 ... ... 现给定任意 4 位正整数,请编写程序演示到达黑洞的过程。 输入格式: 输入给出一个 (0,10^4 ) 区间内的正整数 N。 输出格式: 如果 N 的 4 位数字全相等,则在一行内输出 N - N = 0000;否则将计算的每一步在一行内输出,直到 6174 作为差出现,输出格式见样例。注意每个数字按 4 位数格式输出。 输入样例 1: 6767 输出样例 1: 7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 输入样例 2: 2222 输出样例 2: 2222 - 2222 = 0000
AC代码:
// 1019 数字黑洞 // 一个测试点没有通过 # include <stdio.h> int main(void) { int val; // 记录输入的数字 int i, j; int N[4]; int max=0, min=0; scanf("%d",&val); // 将数字拆分 for (i=0; i<4; i++) { N[i] = val%10; val /= 10; } // 升序排序 for (i=1; i<4; i++) { for (j=0; j<4; j++) { if (N[i] < N[j]) { val = N[i]; N[i] = N[j]; N[j] = val; } } } min = N[0]*1000+N[1]*100+N[2]*10+N[3]; max = N[3]*1000+N[2]*100+N[1]*10+N[0]; val = max - min; while (1) { // 学会控制输出格式 用0补齐 printf("%04d - %04d = %04d\n",max,min, val); if (val==0 || val==6174) break; // 将数字拆分 for (i=0; i<4; i++) { N[i] = val%10; val /= 10; } // 升序排序 for (i=1; i<4; i++) { for (j=0; j<4; j++) { if (N[i] < N[j]) { val = N[i]; N[i] = N[j]; N[j] = val; } } } min = N[0]*1000+N[1]*100+N[2]*10+N[3]; max = N[3]*1000+N[2]*100+N[1]*10+N[0]; val = max - min; } return 0; }
PAT_B_1020 月饼
题目描述:
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。 注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。 输入格式: 每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。 输出格式: 对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。 输入样例: 3 20 18 15 10 75 72 45 输出样例: 94.50
AC代码:
// PAT_1020_月饼 # include <stdio.h> # include <stdlib.h> typedef struct Node { double Cun; double Shou; double M; }NODE, *pNode; int main(void) { int N; // Number double Max; // Needs int i, j; double In = 0.0; scanf("%d",&N); scanf("%lf",&Max); NODE No; pNode node = (pNode)malloc(sizeof(NODE)*N); //输入信息,并计算性价比 for (i=0; i<N; i++) { scanf("%lf",&node[i].Cun); } for (i=0; i<N; i++) { scanf("%lf",&node[i].Shou); node[i].M = (double)node[i].Shou/(double)node[i].Cun; } // 排序 for (i=1; i<N; i++) { for (j=0; j<i; j++) { if (node[i].M > node[j].M) { No = node[i]; node[i] = node[j]; node[j] = No; } } } // 遍历 // for (i=0; i<N; i++) // { // printf("i = %d Cun = %d, Xingjiabi = %f\n",i,node[i].Cun,node[i].M); // } i=0; // 开始计算 while (Max > 0 && i!=N) { if (node[i].Cun <= Max) { In += node[i].Shou; Max -= node[i].Cun; i++; } else { In = In+(Max*node[i].M); break; } } printf("%.2f\n",In); return 0; }
PAT_B_1021 个位数统计
题目描述:
给定一个 k 位整数 N=dk−1 10k−1 +⋯+d1 101 +d0 (0≤di ≤9, i=0,⋯,k−1, dk−1 >0), 请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。 输入格式: 每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。 输出格式: 对 N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。 输入样例: 100311 输出样例: 0:2 1:3 3:1
AC代码:
// PAT乙级 // PAT_1021_Count // 把输入的数据按位拆分,并输出0-9出现的次数 # include <stdio.h> # include <stdlib.h> # include <string.h> int main(void) { char ch[1001]; // 记录输入的数据 int i, len; int Count[10] = {0}; // 输入字符串 gets(ch); len = strlen(ch); // 统计0-9出现的次数 for (i=0; i<len; i++) { Count[(ch[i]-'0')]++; } for (i=0; i<10; i++) { if (Count[i] != 0) printf("%d:%d\n",i,Count[i]); } return 0; }
PAT_B_1022 D进制的A+B
题目描述:
输入两个非负 10 进制整数 A 和 B (≤2^30 −1),输出 A+B 的 D (1<D≤10)进制数。 输入格式: 输入在一行中依次给出 3 个整数 A、B 和 D。 输出格式: 输出 A+B 的 D 进制数。 输入样例: 123 456 8 输出样例: 1103
AC代码:
// PAT乙级 // PAT_1022_System // 对10进制的数据家和结果进行进制转换 # include <stdio.h> # define Max 32 int main(void) { long A, B, Sum; int i, D; int System[Max+1]; // 记录转换之后的数据 // 输入数据 scanf("%ld",&A); scanf("%ld",&B); scanf("%d",&D); // 计算A+B Sum = A+B; if (Sum == 0) { printf("0"); return 0; } // 进制转换 for (i=Max; i>=0; i--) { System[i] = -1; } i=0; while (Sum != 0) { System[i++] = Sum%D; Sum /= D; } for (i=Max; i>=0; i--) { if (System[i] != -1) printf("%d",System[i]); } return 0; }
PAT_B_1023 组个最小数
题目描述:
给定数字 0-9 各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意 0 不能做首位)。例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的最小的数就是 10015558。 现给定数字,请编写程序输出能够组成的最小的数。 输入格式: 输入在一行中给出 10 个非负整数,顺序表示我们拥有数字 0、数字 1、……数字 9 的个数。整数间用一个空格分隔。10 个数字的总个数不超过 50,且至少拥有 1 个非 0 的数字。 输出格式: 在一行中输出能够组成的最小的数。 输入样例: 2 2 0 0 0 3 0 0 1 0 输出样例: 10015558
AC代码:
// PAT_1023_Min_Number # include <stdio.h> int main(void) { int i, j, k=0; int N[10]; int New[50]; int len = 0; for (i=0; i<10; i++) { scanf("%d",&N[i]); len += N[i]; } // 输入数据 for (i=0; i<10; i++) { for (j=0; j<N[i]; j++) { New[k++] = i; } } // 调整格式 if (New[0] == 0) { for (i=1; i<len; i++) { if (New[i] != 0) { New[0] = New[i]; New[i] = 0; break; } } } // 输出数组 for (i=0; i<len; i++) { printf("%d",New[i]); } return 0; }
PAT_B_1024 科学计数法
题目描述:
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。 现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。 输入格式: 每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。 输出格式: 对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。 输入样例 1: +1.23400E-03 输出样例 1: 0.00123400 输入样例 2: -1.2E+10 输出样例 2: -12000000000
解题关键:
1. 利用字符串对数字的读入;
2. 对符号的判断,正号不必输出,负号必须输出;
3. 对指数的讨论,先把字符串转化为整数后分正负分别计算;
(1).指数为负,则在符号位后直接输出‘0.’,然后在小数点与第一位非0数之间插‘0’,不必再次输出小数点;
(2).指数为正,则判断原字符串在小数点和E之间的长度len与指数exp的大小,再判断小数点的位置。
AC代码:
// PAT_1024_科学计数法 # include <stdio.h> # include <string.h> # include <stdlib.h> # define Max 100000 int main(void) { char S[Max], S_num[Max]; int i=0, j=0, exp, len=0; gets(S); // puts(S); // 输出该数字的符号(数不必输出) if (S[0] == '-') printf("%c",S[0]); while (S[i]!='E') i++; // 提取E后面的数字 strcpy(S_num, S+i+1); // puts(S_num); // 转化为整型数字 exp = atoi(S_num); // printf("%d\n",exp); // 指数分正负讨论,负数时 if (exp<0) { printf("0."); // 在小数点后面输出0 for (j=exp; j<-1; j++) printf("0"); // 输出正负号到E之间的除小数点外的字符 for (i=1; S[i]!='E'; i++) { if (S[i]!='.') printf("%c",S[i]); } } // 指数为正时 else { // 记录小数点到E之间的字符串长度 for (i=2; S[i]!='E'; i++) { if (S[i]!='.') len++; } // 长度 // printf("%d\n",len); // 比较 指数exp 和 长度len 的大小 // exp>len 在最后补零,不用输出 小数点 if (exp >= len) { for (i=1; S[i]!='E'; i++) { if (S[i]!='.') printf("%c",S[i]); } for (i=0; i<exp-len; i++) printf("0"); } // exp < len 在第exp位输出小数点 else { for (i=1; S[i]!='E'; i++) { if (S[i] != '.') printf("%c",S[i]); if (i==exp+2) printf("."); } } } return 0; }
PAT_B_1026 程序运行时间
题目描述:
要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间。这个时间单位是 clock tick,即“时钟打点”。同时还有一个常数 CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数 f 的运行时间,我们只要在调用 f 之前先调用 clock(),获得一个时钟打点数 C1;在 f 执行完成后再调用 clock(),获得另一个时钟打点数 C2;两次获得的时钟打点数之差 (C2-C1) 就是 f 运行所消耗的时钟打点数,再除以常数 CLK_TCK,就得到了以秒为单位的运行时间。 这里不妨简单假设常数 CLK_TCK 为 100。现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。 输入格式: 输入在一行中顺序给出 2 个整数 C1 和 C2。注意两次获得的时钟打点数肯定不相同,即 C1 < C2,并且取值在 [0,10^7 ]。 输出格式: 在一行中输出被测函数运行的时间。运行时间必须按照 hh:mm:ss(即2位的 时:分:秒)格式输出;不足 1 秒的时间四舍五入到秒。 输入样例: 123 4577973 输出样例: 12:42:59
AC代码:
// PAT_1026_Time # include <stdio.h> # include <stdlib.h> int main(void) { int N1, N2; int hh, mm, ss, flag; scanf("%d",&N1); scanf("%d",&N2); // 看是否四舍五入 flag = (N2-N1)%100; if (flag <= 49) { ss = (N2-N1)/100; } else ss = (N2-N1)/100+1; // 计算小时 hh = ss/3600; ss = ss - hh*3600; mm = ss/60; ss = ss - mm*60; if (hh<10) { printf("0"); } printf("%d:",hh); if (mm<10) { printf("0"); } printf("%d:",mm); if (ss<10) { printf("0"); } printf("%d",ss); return 0; }
PAT_B_1027 打印沙漏
题目描述:
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。 给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。 输入格式: 输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。 输出格式: 首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。 输入样例: 19 * 输出样例: ***** *** * *** ***** 2
AC代码:
// PAT_1027_Print # include <stdio.h> # include <math.h> int main(void) { int number; char ch; int min=1, max; int i, j, k; int left; int val; scanf("%d %c",&number,&ch); if (number < 7) { printf ("%c\n%d",ch,number-1); return 0; } // 用数学公式得到打印的单侧行数 K k = (int)sqrt(2*number + 2) - 1; left = number - ((k+1)*(k+1)-2)/2; k /= 2; // 打印沙漏 由大到小 for (i=k; i>=0; i--) { // 每层有多少个* val = (2*i+1); for (j=0; j<k-i; j++) printf(" "); for (j=0; j<val; j++) { printf("%c",ch); } printf("\n"); } // 打印沙漏 由小到大 for (i=1; i<=k; i++) { // 每层有多少个* val = (2*i+1); for (j=0; j<k-i; j++) printf(" "); for (j=0; j<val; j++) { printf("%c",ch); } printf("\n"); } printf("%d",left); return 0; }
PAT_B_1028 人口普查
题目描述:
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。 输入格式: 输入在第一行给出正整数 N,取值在(0,10^5 ];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按 yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。 输出格式: 在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。 输入样例: 5 John 2001/05/12 Tom 1814/09/06 Ann 2121/01/30 James 1814/09/05 Steve 1967/11/20 输出样例: 3 Tom John
AC代码:
// PAT_1028_Count_Population_02 /* * 1. 输入格式正确的前提下,可以将字符串形式的日期转为整数,直接判断年龄是否合理 * 2. 2014/9/6之后 和 1814/9/6之前,为不合理年龄 * 3. 考虑 全为不合理年龄的情况 */ #include <stdio.h> #include <string.h> int main() { int N;//人数 scanf("%d", &N); char name[6], young_name[6], old_name[6]; int year, month, day, cnt = 0;//年月日,有效生日的个数 int maxAge = 2014*10000 + 9*100 + 6;//不合理年龄的临界点 int minAge = 1814*10000 + 9*100 + 5; for (int i = 0; i < N; i++) { scanf("%s %d/%d/%d", name, &year, &month, &day); int age = year*10000 + month*100 + day; if (age < maxAge && age > minAge) {//如果是合理年龄 cnt++; if (age < maxAge ) {//最年长 maxAge = age; strcpy(old_name, name); } if (age > minAge) {//最年幼 minAge = age; strcpy(young_name, name); } } } if (cnt != 0) { printf("%d %s %s\n", cnt, old_name, young_name); } else {//全为无效生日 printf("0\n"); } return 0; }
PAT_B_1029 旧键盘
题目描述:
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。 输入格式: 输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。 输出格式: 按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。 输入样例: 7_This_is_a_test _hs_s_a_es 输出样例: 7TI
AC代码:
// PAT_1029_Broken_Key # include <stdio.h> # include <string.h> int main(void) { char S1[100]; // 记录本应该输入的字符 char S2[100]; // 记录实际输出的字符 char Break_Key[85]; // 记录坏掉的键 int i=0, j=0, k=0; int len1, len2; int flag = 1; int n = 0; // 记录坏掉的键个数 // 输入字符串 gets(S1); gets(S2); len1 = strlen(S1); len2 = strlen(S2); for(i=0;i<strlen(S1);i++) { if(S1[i]>='a'&&S1[i]<='z') S1[i]=S1[i]-32; } for(i=0;i<strlen(S2);i++) { if(S2[i]>='a'&&S2[i]<='z') S2[i]=S2[i]-32; } i=j=0; // 开始比对字符串 while (i<len1 || j<len2) { // 如果对应位置不相同,则说明该键是坏键 // 有坏键则S2下标不动 if (S1[i] != S2[j]) { // 判断是否在已经坏掉的字符串中出现过 k=0; flag = 1; while (Break_Key[k] != '\0') { // 如果S1[i] 在Break_Key 字符串中出现过,则不再继续,设置标志符号flag=0; if (S1[i] == Break_Key[k]) { flag = 0; break; } k++; } // 写入的时候,字母大写 if (flag == 1) { Break_Key[n] = S1[i]; n++; } i++; } // 否则,说明该键没问题 else { i++; j++; } } for (i=0; i<n; i++) { printf("%c",Break_Key[i]); } printf("\n"); return 0; }
PAT_B_1030_完美数列
题目描述:
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。 现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。 输入格式: 输入第一行给出两个正整数 N 和 p,其中 N(≤100,000 )是输入的正整数的个数, p(≤1,000,000,000 )是给定的参数。第二行给出 N 个正整数,每个数不超过 1,000,000,000 。 输出格式: 在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。 输入样例: 10 8 2 3 20 4 5 1 6 7 8 9 输出样例: 8
使用C语言解释:
在准备机试时学会了利用C++的库函数简化代码量 1. 利用 vector 构造一个数组
用法: vector<int> A(N); // 建立一个数组名为A,数据类型为int,长度为N的数组 2. 利用sort()库函数对数组进行排序
用法:sort(A.begin(), A.end()); // 对上述A数组从头到尾排序
核心思想:
// 每次循环时 A[i] 是新数组的最小值,A[j]为最大值 // 已知累计长度最大为max,仅仅考虑是否更新max值即可 // 则A[i]到A[i+max]之间的值不必再次比较 // 并且计算A[i]往后还有多长,如果小于max则自动退出,不必检查 left = N - i + 1; if (left <= max) break; // 计算最大长度 // 此时最小值为A[i],最大值A[j] len = j-i+1; // 如果当前长度比累计最大值大,则更新最大值
AC代码:
// 1030 完美数列 # include <stdio.h> # include <algorithm> # include <stdlib.h> # include <vector> using namespace std; // 必写 int main(void) { int N; long P; int i, j; int left; // 数组剩余长度 int len=0, max = 0; // 分别代表此时遍历时的长度(len),以及累计最大值max scanf("%d",&N); scanf("%ld",&P); // 利用库函数建立数组并进行排序 vector<int> A(N); for (i=0; i<N; i++) { scanf("%d",&A[i]); } sort(A.begin(), A.end()); for (i=0; i<N; i++) { // A[i] 是新数组的最小值,A[j]为最大值 // 已知累计长度最大为max,仅仅考虑是否更新max值即可 // 则A[i]到A[i+max]之间的值不必再次比较 for (j=i+max; j<N; j++) { // 计算A[i]往后还有多长,如果小于max则自动退出,不必检查 left = N - i + 1; if (left <= max) break; // 计算最大长度 // 此时最小值为A[i],最大值A[j] if (A[i]*P >= A[j]) { len = j-i+1; //printf("A[i] = %d,A[j] = %d,===>%d\n",A[i],A[j],len); // 如果当前长度比累计最大值大,则更新最大值 if (len > max) max = len; } else { break; } } } printf("%d",max); return 0; }
PAT_B_1031 查验身份证
题目描述:
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值: Z:0 1 2 3 4 5 6 7 8 9 10 M:1 0 X 9 8 7 6 5 4 3 2 现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。 输入格式: 输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。 输出格式: 按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed。 输入样例1: 4 320124198808240056 12010X198901011234 110108196711301866 37070419881216001X 输出样例1: 12010X198901011234 110108196711301866 37070419881216001X 输入样例2: 2 320124198808240056 110108196711301862 输出样例2: All passed
本人AC代码:
// PAT_1031_Check_ID // 检验身份证号码是否合理 # include <stdio.h> # include <stdlib.h> # include <string.h> typedef struct { char ID[18]; // 18位身份证号码 }Node, * NODE; int main(void) { NODE node; int Weigh[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; // 注意,此处输入字符类型不用加‘’ char M[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; int n; // 记录输入数据的个数 int i, j; int len = 1; int *Sum, *flag; // 分别用来计算结果和判断是否合法的标志 scanf("%d",&n); // 动态分配内存 node = (NODE)malloc(sizeof(Node)*n); Sum = (int *)malloc(sizeof(int)*n); flag = (int *)malloc(sizeof(int)*n); // 输入信息 for (i=0; i<n; i++) { scanf("%s",node[i].ID); // 输入ID Sum[i] = 0; flag[i] = 0; } // 计算是否合法 for (i=0; i<n; i++) { for (j=0; j<17; j++) { // 判断前17位是否全是数字 if (node[i].ID[j]>='0' && node[i].ID[j]<='9') { flag[i] = 1; } else { // 如果不符合,即刻 退出此次循环 flag[i] = -1; break; } } // 如果发现不符合输入规定的,置len 标志位为-1 if (flag[i] == -1) len = 0; } // 计算加权之和 for (i=0; i<n; i++) { // 针对输入合法的ID进行校验 if (flag[i] != -1) { for (j=0; j<17; j++) { Sum[i] += (node[i].ID[j]-'0')*Weigh[j]; } } // 比对校验位 if (M[Sum[i]%11] == node[i].ID[17]) { flag[i] = 1; } else { flag[i] = -1; len = 0; } } // 输出信息 if (len == 1) printf("All passed\n"); else { for (i=0; i<n; i++) { if (flag[i] != 1) { for (j=0; j<18; j++) { printf("%c",node[i].ID[j]); } printf("\n"); } } } return 0; }
PAT_B_1032_挖掘机技术哪家强
题目描述:
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛。现请你根据比赛结果统计出技术最强的那个学校。 输入格式: 输入在第 1 行给出不超过 100000 的正整数 N,即参赛人数。随后 N 行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从 1 开始连续编号)、及其比赛成绩(百分制),中间以空格分隔。 输出格式: 在一行中给出总得分最高的学校的编号、及其总分,中间以空格分隔。题目保证答案唯一,没有并列。 输入样例: 6 3 65 2 80 1 100 2 70 3 40 3 0 输出样例: 2 150
AC代码:
// 挖掘机技术哪家强 # include <stdio.h> # define Max 100001 // 避免数组越界 int main(void) { int N; int i, val, len; int A[Max] = {0}; int Max_num, Max_Arr; scanf("%d",&N); len = N; while (len > 0) { scanf("%d",&i); scanf("%d",&val); A[i] += val; len--; } Max_num = 0; A[Max_num] = Max_Arr; for (i=1; i<=N; i++) {// 排序 if (A[i] > A[Max_num]) { Max_num = i; Max_Arr = A[i]; } } printf("%d %d",Max_num, Max_Arr); return 0; }
PAT_B_1033 旧键盘打字
题目描述
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 行中分别给出坏掉的那些键、以及应该输入的文字。其中对应英文字母的坏键以大写给出;每段文字是不超过 10^5个字符的串。 可用的字符包括字母 [a-z, A-Z]、数字 0-9、以及下划线 _(代表空格)、,、.、-、+(代表上档键)。题目保证第 2 行输入的文字串非空。 注意:如果上档键坏掉了,那么大写的英文字母无法被打出。 输出格式: 在一行中输出能够被打出的结果文字。如果没有一个字符能被打出,则输出空行。 输入样例: 7+IE. 7_This_is_a_test. 输出样例: _hs_s_a_tst
AC代码
// PAT_1033_Type # include <stdio.h> # include <string.h> int main(void) { char Break[50]; char S_Arr[100010]; char Err[] = ""; int len; int i, j=0; int flag_UP = 0; // 如果flag_UP为0,表示没坏,则大写字母正常输出 int flag = 1; // 标志每一位是否输出 int flag_All = 0; gets(Break); // 输入键盘的坏键 gets(S_Arr); // 输入文本段 if (Break == "") { puts(S_Arr); return 0; } len = strlen(S_Arr); // 清除无法显示的字符 // 先遍历一遍Break,看是否有上档键失灵,如果有定义flag_UP=1不输出大写字母 while (Break[j] != '\0') { if (Break[j]=='+') { flag_UP = 1; } j++; } for (i=0; i<len; i++) { j = 0; flag = 1; // 挨个遍历S_Arr,如果flag为0 则不输出 // 首先判断是否是字母,如果不是字母,则不用判断大小写 // 开始判断字母是否符合 // 小写字母 if (S_Arr[i]>='a'&&S_Arr[i]<='z') { while (Break[j] != '\0') { if ((S_Arr[i]-'a' == Break[j]-'A')) { flag = 0; break; } j++; } } else if (S_Arr[i]>='A'&&S_Arr[i]<='Z') { if (flag_UP == 1) { // 上档键坏了则,大写字母不输出 flag = 0; } else { while (Break[j] != '\0') { if (S_Arr[i] == Break[j]) { flag = 0; break; } j++; } } } else { while (Break[j] != '\0') { if (S_Arr[i] == Break[j]) { flag = 0; break; } j++; } } if (flag == 1) { flag_All = 1; printf("%c",S_Arr[i]); } } if (flag_All == 0) { printf(""); } return 0; }
PAT_B_1034 有理数四则运算
题目描述
本题要求编写程序,计算 2 个有理数的和、差、积、商。 输入格式: 输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前,分母不为 0。 输出格式: 分别在 4 行中按照 有理数1 运算符 有理数2 = 结果 的格式顺序输出 2 个有理数的和、差、积、商。注意输出的每个有理数必须是该有理数的最简形式 k a/b,其中 k 是整数部分,a/b 是最简分数部分;若为负数,则须加括号;若除法分母为 0,则输出 Inf。题目保证正确的输出中没有超过整型范围的整数。 输入样例 1: 2/3 -4/2 输出样例 1: 2/3 + (-2) = (-1 1/3) 2/3 - (-2) = 2 2/3 2/3 * (-2) = (-1 1/3) 2/3 / (-2) = (-1/3) 输入样例 2: 5/3 0/6 输出样例 2: 1 2/3 + 0 = 1 2/3 1 2/3 - 0 = 1 2/3 1 2/3 * 0 = 0 1 2/3 / 0 = Inf
AC代码
#include <stdio.h> long calcgcd(long a, long b) { long r; while((r = a % b)) { a = b; b = r; } return b; } void printfrac(long n, long d) { if(d == 0) { printf("Inf"); return; } int inegative = 1; if(n < 0) { n = -n; inegative *= -1; } if(d < 0) { d = -d; inegative *= -1; } long gcd = calcgcd(n, d); n /= gcd; d /= gcd; if(inegative == -1) printf("(-"); if(n / d && n % d) printf("%ld %ld/%ld", n / d, n % d, d); else if(n % d) printf("%ld/%ld", n % d, d); else printf("%ld", n / d); if(inegative == -1) printf(")"); } int main() { long a1, b1, a2, b2; scanf("%ld/%ld %ld/%ld", &a1, &b1, &a2, &b2); char op[4] = {'+', '-', '*', '/'}; for(int i = 0; i < 4; i++) { printfrac(a1, b1); printf(" %c ", op[i]); printfrac(a2, b2); printf(" = "); switch(op[i]) { case '+': printfrac(a1 * b2 + a2 * b1, b1 * b2); break; case '-': printfrac(a1 * b2 - a2 * b1, b1 * b2); break; case '*': printfrac(a1 * a2, b1 * b2); break; case '/': printfrac(a1 * b2, b1 * a2); break; } printf("\n"); } return 0; }
PAT_B_1036 跟奥巴马一起编程
题目描述
美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。2014 年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正方形。现在你也跟他一起画吧! 输入格式: 输入在一行中给出正方形边长 N(3≤N≤20)和组成正方形边的某种字符 C,间隔一个空格。 输出格式: 输出由给定字符 C 画出的正方形。但是注意到行间距比列间距大,所以为了让结果看上去更像正方形,我们输出的行数实际上是列数的 50%(四舍五入取整)。 输入样例: 10 a 输出样例: aaaaaaaaaa a a a a a a aaaaaaaaaa
AC代码
// PAT_1036_Program # include <stdio.h> int main(void) { int m, n; char ch; int i, j; scanf("%d %c",&n, &ch); // 计算列 m = (n%2==1)?(n+1)/2:n/2; for (i=0; i<m; i++) { for (j=0; j<n; j++) { if (i==0 || j==0 || i==m-1 || j==n-1) { printf("%c",ch); } else printf(" "); } printf("\n"); } return 0; }
PAT_B_1038 统计同成绩学生
题目描述
题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出。 输入格式: 输入在第 1 行给出不超过 10^5 的正整数 N,即学生总人数。随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔。最后一行给出要查询的分数个数 K(不超过 N 的正整数),随后是 K 个分数,中间以空格分隔。 输出格式: 在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。 输入样例: 10 60 75 90 55 75 99 82 90 75 50 3 75 90 88 输出样例: 3 2 0
AC代码
// PAT_1038_COUNT_GRADES_02 // 运行超时,用空间换时间 # include <stdio.h> # include <stdlib.h> # define Max 110 int main(void) { int n, k; int i; int val; scanf("%d",&n); int Grades[110]; // 将成绩数组初始化为0,代表给分数有多少人 for (i=0; i<Max; i++) { Grades[i] = 0; } // 记录每个分数的人数 for (i=0; i<n; i++) { scanf("%d",&val); Grades[val] ++; } scanf("%d",&k); for (i=0; i<k; i++) { scanf("%d",&val); // 查找 printf("%d",Grades[val]); // 控制输出格式 if (i != k-1) printf(" "); } return 0; }
PAT_B_1040 有几个PAT
题目描述
字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T);第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T)。 现给定字符串,问一共可以形成多少个 PAT? 输入格式: 输入只有一行,包含一个字符串,长度不超过10^5 ,只包含 P、A、T 三种字母。 输出格式: 在一行中输出给定字符串中包含多少个 PAT。由于结果可能比较大,只输出对 1000000007 取余数的结果。 输入样例: APPAPT 输出样例: 2
AC代码
// 参照别人的巧妙解法 #include <stdio.h> #define LIM 1000000007 int main() { int P = 0, PA = 0, PAT = 0; char c; while((c = getchar()) != '\n') { if(c == 'P') P++; if(c == 'A') PA = (PA + P) % LIM; if(c == 'T') PAT = (PAT + PA) % LIM; } printf("%d", PAT); return 0; }
PAT_B_1041 考试座位号
题目描述
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。 输入格式: 输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 16 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。 考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。 输出格式: 对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。 输入样例: 4 3310120150912233 2 4 3310120150912119 4 1 3310120150912126 1 3 3310120150912002 3 2 2 3 4 输出样例: 3310120150912002 2 3310120150912119 1
AC代码
// PAT_1041_Number_ID # include <stdio.h> # include <stdlib.h> typedef struct Node { char ch[18]; int n1, n2; }NODE, *pNODE; int main(void) { int n, m, search; int i, j; int N_i; int flag = 0; scanf("%d",&n); pNODE node = (pNODE)malloc(sizeof(NODE)*n); // 输入 考生信息 for (i=0; i<n; i++) { scanf("%s",node[i].ch); scanf("%d",&node[i].n1); scanf("%d",&node[i].n2); } // 输入要查询的内容 scanf("%d",&m); // 查询 for (i=0; i<m; i++) { scanf("%d",&search); flag = 0; // 在已经输入的信息中查询 for (j=0; j<n; j++) { if (search == node[j].n1) { // 如果找到了,则flag 设置为1 N_i = j; flag = 1; break; } } // 输出信息 if (flag == 1) { for (j=0; j<16; j++) { printf("%c",node[N_i].ch[j]); } printf(" %d\n",node[N_i].n2); } } return 0; }
解题思路
0. 准考证号长度为16位,可以采用 long long 类型存储
1. 先读取准考证号、机试座号和考试座号
2. 把准考证号和考试座号存入下标为机试座号的数组中
3. 最后直接通过机试座号读取两个数组的数据即可
AC代码(改进版)
# include <stdio.h> # include <stdlib.h> # include <string.h> # define Max 1002 int main(void) { long long Num[Max], a; int flag, i; int S_num[Max], b; int len_0, len_1; scanf("%d",&len_0); // 先读取准考证号、机试座号和考试座号 for (i=0; i<len_0; i++) { scanf("%lld",&a); scanf("%d",&flag); scanf("%d",&b); // 把准考证号和考试座号存入下标为机试座号的数组中 Num[flag] = a; S_num[flag] = b; } scanf("%d",&len_1); for (i=0; i<len_1; i++) { scanf("%d",&flag); printf("%lld %d\n",Num[flag],S_num[flag]); } return 0; }
PAT_B_1042 字符统计
题目描述
请编写程序,找出一段给定文字中出现最频繁的那个英文字母。 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串。字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母,以回车结束(回车不算在内)。 输出格式: 在一行中输出出现频率最高的那个英文字母及其出现次数,其间以空格分隔。如果有并列,则输出按字母序最小的那个字母。统计时不区分大小写,输出小写字母。 输入样例: This is a simple TEST. There ARE numbers and other symbols 1&2&3........... 输出样例: e 7
AC代码
// PAT_1042_Count_Vocabulary # include <stdio.h> # include <string.h> int main(void) { int Voc[26]; int num, max; char S[1001]; int i; gets(S); for (i=0; i<26; i++) { Voc[i]=0; } i=0; while (S[i] != '\0') { if (S[i]>='a' && S[i]<='z') { num = S[i] - 'a'; Voc[num]++; } else if (S[i]>='A' && S[i]<='z') { num = S[i] - 'A'; Voc[num]++; } i++; } max = 25; for (i=24; i>=0; i--) { if (Voc[i] >= Voc[max]) { max = i; } } printf("%c %d",'a'+max,Voc[max]); return 0; }
PAT_B_1043 输出PATest
题目描述
给定一个长度不超过 10^4 的、仅由英文字母构成的字符串。请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符。当然,六种字符的个数不一定是一样多的,若某种字符已经输出完,则余下的字符仍按 PATest 的顺序打印,直到所有字符都被输出。 输入格式: 输入在一行中给出一个长度不超过 10^4 的、仅由英文字母构成的非空字符串。 输出格式: 在一行中按题目要求输出排序后的字符串。题目保证输出非空。 输入样例: redlesPayBestPATTopTeePHPereatitAPPT 输出样例: PATestPATestPTetPTePePee
AC代码
// PAT_1043_PATest # include <stdio.h> # include <string.h> int main(void) { char S[10010]; int i = 0; int P=0, A=0, T=0, e=0, s=0, t=0; gets(S); while (S[i] != '\0') { if (S[i] == 'P') { P++; } else if (S[i] == 'A') { A++; } else if (S[i] == 'T') { T++; } else if (S[i] == 'e') { e++; } else if (S[i] == 's') { s++; } else if (S[i] == 't') { t++; } i++; } while (P+A+T+e+s+t != 0) { if (P!=0) { printf("P"); P--; } if (A!=0) { printf("A"); A--; } if (T!=0) { printf("T"); T--; } if (e!=0) { printf("e"); e--; } if (s!=0) { printf("s"); s--; } if (t!=0) { printf("t"); t--; } } return 0; }
PAT_B_1044 火星数字
题目描述
火星人是以 13 进制计数的: 地球人的 0 被火星人称为 tret。 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。 火星人将进位以后的 12 个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。 例如地球人的数字 29 翻译成火星文就是 hel mar;而火星文 elo nov 对应地球数字 115。为了方便交流,请你编写程序实现地球和火星数字之间的互译。 输入格式: 输入第一行给出一个正整数 N(<100),随后 N 行,每行给出一个 [0, 169) 区间内的数字 —— 或者是地球文,或者是火星文。 输出格式: 对应输入的每一行,在一行中输出翻译后的另一种语言的数字。 输入样例: 4 29 5 elo nov tam 输出样例: hel mar may 115 13
AC代码
// PAT_1044_Mars # include <stdio.h> # include <string.h> # include <stdlib.h> # define Max 10 char *a[] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"}; char *b[] = {"***","tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"}; char S[Max]; // 火星文转为地球 void Mars2Earth() { char AS[4]={""}, BS[4]={""}; int num1=0, num2=0; int len, i; len = strlen(S); // 判断位数,如果字符串长度大于 4,则有十位 // BS 存储前三位 strncpy(BS, S, 3); if (len > 4) strcpy(AS, S+4); // 转化 for (i=1; i<=12; i++) { if (!strcmp(BS, a[i]) || !strcmp(AS, a[i])) num2 = i; if (!strcmp(BS, b[i])) num1 = i; } printf("%d",num1*13+num2); } // 地球文字转为火星文 void Earth2Mars(int num) { // 判断十位是否输出 if (num/13 != 0) printf("%s",b[num/13]); // 控制空格的输出 if (num%13 != 0 && num>13) printf(" "); // 判断个位是否输出 if (num%13 || num==0) printf("%s",a[num%13]); } int main(void) { int N, i; scanf("%d",&N); getchar(); for (i=0; i<N; i++) { gets(S); // 根据第一位判断是地球数字还是火星文 if (S[0]>='0' && S[0]<='9') { Earth2Mars(atoi(S)); } else Mars2Earth(); printf("\n"); } return 0; }
PAT_B_1045_快速排序
题目描述:
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元? 例如给定 $N = 5$, 排列是1、3、2、4、5。则: 1 的左边没有元素,右边的元素都比它大,所以它可能是主元; 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元; 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元; 类似原因,4 和 5 都可能是主元。 因此,有 3 个元素可能是主元。 输入格式: 输入在第 1 行中给出一个正整数 N(≤105 ) 第 2 行是空格分隔的 N 个不同的正整数每个数不超过 109 输出格式: 在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。 输入样例: 5 1 3 2 4 5 输出样例: 3 1 4 5
AC代码:
// 1045 快速排序 # include <stdio.h> # include <algorithm> # define Max 100001 using namespace std; // 排序后元素位置不发生变化则可能是主元 int main(void) { int n, num=0, i, max=0; int A[Max], B[Max], C[Max]; scanf("%d",&n); for (i=0; i<n; i++) { scanf("%d",&A[i]); B[i] = A[i]; } sort(A, A+n); for (i=0; i<n; i++) { if (A[i] == B[i] && B[i]>max) { C[num++] = B[i]; } if (B[i] > max) { max = B[i]; } } printf("%d\n",num); if (0 == num) { printf("\n"); return 0; } for (i=0; i<num; i++) { if (i!=0) printf(" "); printf("%d",C[i]); } printf("\n"); return 0; }
PAT_B_1046 划拳
题目描述
划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。 下面给出甲、乙两人的划拳记录,请你统计他们最后分别喝了多少杯酒。 输入格式: 输入第一行先给出一个正整数 N(≤100),随后 N 行,每行给出一轮划拳的记录,格式为: 甲喊 甲划 乙喊 乙划 其中喊是喊出的数字,划是划出的数字,均为不超过 100 的正整数(两只手一起划)。 输出格式: 在一行中先后输出甲、乙两人喝酒的杯数,其间以一个空格分隔。 输入样例: 5 8 10 9 12 5 10 5 10 3 8 5 12 12 18 1 13 4 16 12 15 输出样例: 1 2
AC代码
// PAT_1046_Fit # include <stdio.h> # include <stdlib.h> typedef struct { int A1; // A 喊 int A2; // A 划 int B1; int B2; }Node, *NODE; int main(void) { int N; int i; int Sum; NODE node; scanf("%d",&N); int Win_A=0, Win_B=0; // 分别记录 A B 赢的次数 // 动态分配内存 node = (NODE)malloc(sizeof(Node)*N); // 依次输入信息 for (i=0; i<N; i++) { scanf("%d",&node[i].A1); scanf("%d",&node[i].A2); scanf("%d",&node[i].B1); scanf("%d",&node[i].B2); Sum = node[i].A1 + node[i].B1; // 判断AB的胜负情况 if (Sum==node[i].A2 && Sum==node[i].B2) continue; if (Sum==node[i].A2) Win_A++; if (Sum==node[i].B2) Win_B++; } // 输出结果 printf("%d %d",Win_B, Win_A); return 0; }
PAT_B_1047_编程团体赛
题目描述:
编程团体赛的规则为:每个参赛队由若干队员组成;所有队员独立比赛;参赛队的成绩为所有队员的成绩和;成绩最高的队获胜。 现给定所有队员的比赛成绩,请你编写程序找出冠军队。 输入格式: 输入第一行给出一个正整数 N(≤10000 ),即所有参赛队员总数。随后 N 行,每行给出一位队员的成绩,格式为:队伍编号-队员编号 成绩,其中队伍编号为 1 到 1000 的正整数,队员编号为 1 到 10 的正整数,成绩为 0 到 100 的整数。 输出格式: 在一行中输出冠军队的编号和总成绩,其间以一个空格分隔。注意:题目保证冠军队是唯一的。 输入样例: 6 3-10 99 11-5 87 102-1 0 102-3 100 11-9 89 3-2 61 输出样例: 11 176
要点反思:
// 对于队伍编号,队员编号,队员成绩的输入可以采用: scanf("%d-%d %d",&t_num,&p_num,&val);
本人AC代码:
// 1047 编程团体赛 # include <stdio.h> # define Max 1001 int main(void) { int N, val, t_num, p_num, i; int max; // 记录得分最高的队伍编号 int final[Max] = {0}; scanf("%d",&N); while (N>0) { scanf("%d-%d %d",&t_num,&p_num,&val); final[t_num] += val; N--; } max = 1; for (i=2; i<Max; i++) { if (final[max] < final[i]) max = i; } printf("%d %d",max, final[max]); return 0; }
PAT_B_1048 数字加密
题目描述
本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。 输入格式: 输入在一行中依次给出 A 和 B,均为不超过 100 位的正整数,其间以空格分隔。 输出格式: 在一行中输出加密后的结果。 输入样例: 1234567 368782971 输出样例: 3695Q8118
AC代码
#include <stdio.h> #include <string.h> int main(){ char a[110],b[110]; char ref[13]={'0','1','2','3','4','5','6','7','8','9','J','Q','K'}; scanf("%s %s",a,b); int n1=strlen(a),n2=strlen(b); int flag=1,i,j; //flag用来记录奇数或偶数 char ans[110]={0};int k=0; for(i=n1-1,j=n2-1;i>=0&&j>=0;i--,j--){ if(flag%2==1){ //奇数 ans[k++]=ref[(a[i]-'0'+b[j]-'0')%13]; } else{ //偶数 int t=b[j]-'0'-(a[i]-'0'); if(t<0) t+=10; ans[k++]=t+'0'; } flag++; } if(i<0){ //A短 int p; for(p=j;p>=0;p--){ if(flag%2==1){ ans[k++]=ref[(0+b[p]-'0')%13]; } else{ int t=b[p]-'0'-0; if(t<0) t+=10; ans[k++]=t+'0'; } flag++; } } if(j<0){ //B短 int p; for(p=i;p>=0;p--){ if(flag%2==1){ ans[k++]=ref[(a[p]-'0'+0)%13]; } else{ int t=0-(a[p]-'0'); if(t<0) t+=10; ans[k++]=t+'0'; } flag++; } } int n3=strlen(ans); for(i=n3-1;i>=0;i--){ printf("%c",ans[i]); } return 0; }
PAT_B_1049 数列的片段和
题目描述
给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 这 10 个片段。 给定正整数数列,求出全部片段包含的所有的数之和。如本例中 10 个片段总和是 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0。 输入格式: 输入第一行给出一个不超过 10^5 的正整数 N,表示数列中数的个数,第二行给出 N 个不超过 1.0 的正数,是数列中的数,其间以空格分隔。 输出格式: 在一行中输出该序列所有片段包含的数之和,精确到小数点后 2 位。 输入样例: 4 0.1 0.2 0.3 0.4 输出样例: 5.00
AC代码
// PAT_1049_数列的片段和 # include <stdio.h> # define Max 100010 int main(void) { int N; int i; double val; // 记录输入的数据 double sum = 0; // 最终求解的和 scanf("%d",&N); // 求权值 for (i=1; i<=N; i++) { scanf("%lf",&val); sum += val * i * (N-i+1); } printf("%.2f",sum); return 0; }
PAT_B_1050_螺旋矩阵
题目描述:
本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。 输入格式: 输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 10 4 ,相邻数字以空格分隔。 输出格式: 输出螺旋矩阵。每行 n 个数字,共 m 行。相邻数字以 1 个空格分隔,行末不得有多余空格。 输入样例: 12 37 76 20 98 76 42 53 95 60 81 58 93 输出样例: 98 95 93 42 37 81 53 20 76 58 60 76
AC代码:
// PAT_1050_螺旋数 # include <stdio.h> # include <math.h> # include <stdlib.h> # include <algorithm> # define Max_Size 10010 # define Min_Size 100 using namespace std; int Get_n(float N) { int i; for (i=(int)sqrt(N);i>0; i--) { if ((int)N%i == 0) return i; } } int main(void) { int N; int i, j, k; int m, n; scanf("%d",&N); n = Get_n(N); m = N/n; int A[N+10]; int B[m+1][n+1]; // 初始化 for (i=0; i<m; i++) { for (j=0; j<n; j++) { B[i][j] = 0; } } for (i=0; i<N; i++) { scanf("%d",&A[i]); } sort(A,A+N); // 排序 // 开始放入 m行n列中去 i=0; j=0; k=N-1; B[i][j] = A[k--]; while (k>=0) { // 向右走 while (!B[i][j+1] && j+1<n ) { B[i][++j] = A[k--]; } // 向下走 while (!B[i+1][j] && i+1<m ) { B[++i][j] = A[k--]; } // 向左走 while (!B[i][j-1] && j-1>=0) { B[i][--j] = A[k--]; } // 向左走 while (!B[i-1][j] && i-1>=0) { B[--i][j] = A[k--]; } } for (i=0; i<m; i++) { for (j=0; j<n; j++) { printf("%d",B[i][j]); if (j<n-1) printf(" "); } printf("\n"); } return 0; }
PAT_B_1059_C语言竞赛
题目描述:
C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛。既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 0、冠军将赢得一份“神秘大奖”(比如很巨大的一本学生研究论文集……)。 1、排名为素数的学生将赢得最好的奖品 —— 小黄人玩偶! 2、其他人将得到巧克力。 给定比赛的最终排名以及一系列参赛者的 ID,你要给出这些参赛者应该获得的奖品。 输入格式: 输入第一行给出一个正整数 N(≤10000 ),是参赛者人数。随后 N 行给出最终排名,每行按排名顺序给出一位参赛者的 ID(4 位数字组成)。接下来给出一个正整数 K 以及 K 个需要查询的 ID。 输出格式: 对每个要查询的 ID,在一行中输出 ID: 奖品,其中奖品或者是 Mystery Award(神秘大奖)、或者是 Minion(小黄人)、或者是 Chocolate(巧克力)。如果所查 ID 根本不在排名里,打印 Are you kidding?(耍我呢?)。如果该 ID 已经查过了(即奖品已经领过了),打印 ID: Checked(不能多吃多占)。 输入样例: 6 1111 6666 8888 1234 5555 0001 6 8888 0001 1111 2222 8888 2222 输出样例: 8888: Minion 0001: Chocolate 1111: Mystery Award 2222: Are you kidding? 8888: Checked 2222: Are you kidding?
解答关键:
// 关键点:控制数字的格式化输出 // 如将整数1按照格式 0001输出 // 则采用下面的输出格式控制,比较简单,不必用字符串控制输出 printf("%04d\n",val);
AC代码:
下述代码改进方法:
// int Class[Max] = {0}; // 5代表特等奖,3代表小黄人,1代表巧克力 // 对每一个数字判断是否为素数,冗余量较高,则在领奖时对相应的序号判断即可 int prime = 0; // 设置参数表示该位置是否为素数
//1059 C语言竞赛 // 关键点:控制数字的格式化输出 # include <stdio.h> # include <math.h> # define Max 10001 int Prime(int ); int main(void) { int Num[Max]; int flag[Max] = {0}; // -1 代表领过奖了 int Class[Max] = {0}; // 5代表特等奖,3代表小黄人,1代表巧克力 int len1, len2, i, j, N, val; int temp = 0; // 设置参数,temp=0,代表没有找到,temp=1,代表找到 scanf("%d",&N); len1 = N; for (i=1; i<=len1; i++) { scanf("%d",&Num[i]); if (1 == Prime(i)) Class[i] = 3; else Class[i] = 1; } Class[1] = 5; scanf("%d",&N); len2 = N; for (i=1; i<=len2; i++) { temp = 0; scanf("%d",&val); // 在Num[]数组中遍历查找val for (j=1; j<=len1; j++) { if (Num[j] == val) { temp = 1; // 设置标志位为1,表示找到了 break; } } // 如果找到,则比较是否领过奖品 if(1 == temp) { // 领过奖品 if (-1 == flag[j]) { printf("%04d: Checked\n",val); } // 没有领过 else if (0 == flag[j]) { if (5 == Class[j]) { printf("%04d: Mystery Award\n",val); } else if (3 == Class[j]) { printf("%04d: Minion\n",val); } else if (1 == Class[j]) { printf("%04d: Chocolate\n",val); } // 领过奖之后设置标志位为-1 flag[j] = -1; } } // 否则,输出Are you kidding? else { printf("%04d: Are you kidding?\n",val); } } return 0; } int Prime(int n) { int i = 2; for (i; i<=sqrt(n); i++) { if (n%i == 0) return 0; } return 1; }
PAT_B_1060 爱丁顿数
题目描述
英国天文学家爱丁顿很喜欢骑车。据说他为了炫耀自己的骑车功力,还定义了一个“爱丁顿数” E ,即满足有 E 天骑车超过 E 英里的最大整数 E。据说爱丁顿自己的 E 等于87。 现给定某人 N 天的骑车距离,请你算出对应的爱丁顿数 E(≤N)。 输入格式: 输入第一行给出一个正整数 N (≤10^5 ),即连续骑车的天数;第二行给出 N 个非负整数,代表每天的骑车距离。 输出格式: 在一行中给出 N 天的爱丁顿数。 输入样例: 10 6 7 6 9 3 10 8 2 7 8 输出样例: 6
分析
// 排序之后发现规律 // 2 3 6 6 7 7 8 8 9 10 // 10 9 8 7 6 5 4 3 2 1 // 第一个天数的倒序小于排序后的距离,该天数即为E
AC代码
// 1060 爱丁顿数 # include <stdio.h> # include <algorithm> # define Max 100001 using namespace std; int main(void) { int a[Max]; int N, i; scanf("%d", &N); for (i=1; i<=N; i++) scanf("%d",&a[i]); sort(a+1,a+N+1); for (i=1; i<=N; i++) { if (a[i] > (N+1-i)) break; } printf("%d\n",N+1-i); return 0; }
PAT_B_1067_试密码
题目描述:
当你试图登录某个系统却忘了密码时,系统一般只会允许你尝试有限多次,当超出允许次数时,账号就会被锁死。本题就请你实现这个小功能。 输入格式: 输入在第一行给出一个密码(长度不超过 20 的、不包含空格、Tab、回车的非空字符串)和一个正整数 N(≤ 10),分别是正确的密码和系统允许尝试的次数。随后每行给出一个以回车结束的非空字符串,是用户尝试输入的密码。输入保证至少有一次尝试。当读到一行只有单个 # 字符时,输入结束,并且这一行不是用户的输入。 输出格式: 对用户的每个输入,如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序;如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码;当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序。 输入样例 1: Correct%pw 3 correct%pw Correct@PW whatisthepassword! Correct%pw # 输出样例 1: Wrong password: correct%pw Wrong password: Correct@PW Wrong password: whatisthepassword! Account locked 输入样例 2: cool@gplt 3 coolman@gplt coollady@gplt cool@gplt try again # 输出样例 2: Wrong password: coolman@gplt Wrong password: coollady@gplt Welcome in
坑点指南:
题目本身没有什么难度,但是以下的坑点值得好好考虑 // 要点:1. 题目中的密码没有空格,但是用户输入时可能会键入空格 // 2. 标准密码的长度是20, 但是用户键入的密码可能会大于20
AC代码:
// 1067 试密码 // 要点:1. 题目中的密码没有空格,但是用户输入时可能会键入空格 // 2. 标准密码的长度是20, 但是用户键入的密码可能会大于20 # include <stdio.h> # include <stdlib.h> # include <string.h> int main(void) { char PassW[22], temp[52]; int num; // 读入标准密码以及允许尝试的次数 scanf("%s %d",PassW,&num); getchar(); while (1) { gets(temp); num--; // 如果仅输入一个# 则停止输入 if (0 == strcmp("#", temp)) { break; } // 比较字符串是否相等 // 如果相等 if (0 == strcmp(PassW, temp) && num>=0) { printf("Welcome in"); // 结束循环 break; } else if (0 != strcmp(PassW, temp) && num>=0) { printf("Wrong password: %s\n",temp); // 次数用尽,账户锁定 // printf("num === %d\n",num); if (0 == num) { printf("Account locked"); break; } } } return 0; }
PAT_B_1069_微博转发抽奖
题目描述:
小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包。请你编写程序帮助他确定中奖名单。 输入格式: 输入第一行给出三个正整数 M(≤ 1000)、N 和 S,分别是转发的总量、小明决定的中奖间隔、以及第一位中奖者的序号(编号从 1 开始)。随后 M 行,顺序给出转发微博的网友的昵称(不超过 20 个字符、不包含空格回车的非空字符串)。 注意:可能有人转发多次,但不能中奖多次。所以如果处于当前中奖位置的网友已经中过奖,则跳过他顺次取下一位。 输出格式: 按照输入的顺序输出中奖名单,每个昵称占一行。如果没有人中奖,则输出 Keep going...。 输入样例 1: 9 3 2 Imgonnawin! PickMe PickMeMeMeee LookHere Imgonnawin! TryAgainAgain TryAgainAgain Imgonnawin! TryAgainAgain 输出样例 1: PickMe Imgonnawin! TryAgainAgain 输入样例 2: 2 3 5 Imgonnawin! PickMe 输出样例 2: Keep going...
题目关键:
注意已中奖账号的存储与比较 如果目标账号已经中奖,则向下顺延
AC代码:
# include <stdio.h> # include <string.h> # define Max 1000 int main() { int n,m,s,i,j,num = 0, flag=0; char str[Max][21],win[Max][21]; scanf("%d %d %d",&m,&n,&s); s--; getchar(); for(i = 0;i < m;i++) gets(str[i]); if(s >= m) { printf("Keep going..."); return 0; } for (i=s; i<m; ) { flag = 0; // 判断是否中过奖 for (j=0; j<num; j++) { if (0 == strcmp(str[i], win[j])) { flag = 1; break; } } // 如没有 if (flag == 0) { puts(str[i]); strcpy(win[num++],str[i]); i+=n; } else // 否则 { i++; } } return 0; }
PAT_B_1072 开学寄语
题目描述
上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其 QQ,封其电脑,夺其手机,收其 ipad,断其 wifi,使其百无聊赖,然后,净面、理发、整衣,然后思过、读书、锻炼、明智、开悟、精进。而后必成大器也! 本题要求你写个程序帮助这所学校的老师检查所有学生的物品,以助其成大器。 输入格式: 输入第一行给出两个正整数 N(≤ 1000)和 M(≤ 6),分别是学生人数和需要被查缴的物品种类数。第二行给出 M 个需要被查缴的物品编号,其中编号为 4 位数字。随后 N 行,每行给出一位学生的姓名缩写(由 1-4 个大写英文字母组成)、个人物品数量 K(0 ≤ K ≤ 10)、以及 K 个物品的编号。 输出格式: 顺次检查每个学生携带的物品,如果有需要被查缴的物品存在,则按以下格式输出该生的信息和其需要被查缴的物品的信息(注意行末不得有多余空格): 姓名缩写: 物品编号1 物品编号2 …… 最后一行输出存在问题的学生的总人数和被查缴物品的总数。 输入样例: 4 2 2333 6666 CYLL 3 1234 2345 3456 U 4 9966 6666 8888 6666 GG 2 2333 7777 JJ 3 0012 6666 2333 输出样例: U: 6666 6666 GG: 2333 JJ: 6666 2333 3 5
AC代码
// 1072 开学寄语 # include <stdio.h> int main(void) { int N, M; int i, j, k, len; char S[6]; int Good[6]={0}, num; int sum_name=0, sum_good=0, flag=0; scanf("%d%d",&N, &M); // 记录违规物品编号 for (i=0; i<M; i++) { scanf("%d",&Good[i]); } // 输入学生姓名及所带物品编号 for (j=0; j<N; j++) { // 姓名 scanf("%s",S); // 物品数量 scanf("%d",&len); // 各个物品编号 flag = 0; // 如果该学生有违规物品,则输出姓名 for (i=0; i<len; i++) { scanf("%d",&num); for (k=0; k<M; k++) { if (flag == 0) if (num==Good[k]) { sum_name++; flag=1; // 已经输出了姓名 printf("%s:",S); } if (num == Good[k]) { // 违规物品数量 sum_good++; printf(" %04d",num); } } } if (flag == 1) printf("\n"); } printf("%d %d\n",sum_name, sum_good); return 0; }
PAT_B_1074 宇宙无敌加法器
题目描述:
地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的。而在 PAT 星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为“PAT数”。每个 PAT 星人都必须熟记各位数字的进制表,例如“……0527”就表示最低位是 7 进制数、第 2 位是 2 进制数、第 3 位是 5 进制数、第 4 位是 10 进制数,等等。每一位的进制 d 或者是 0(表示十进制)、或者是 [2,9] 区间内的整数。理论上这个进制表应该包含无穷多位数字,但从实际应用出发,PAT 星人通常只需要记住前 20 位就够用了,以后各位默认为 10 进制。 在这样的数字系统中,即使是简单的加法运算也变得不简单。例如对应进制表“0527”,该如何计算“6203 + 415”呢?我们得首先计算最低位:3 + 5 = 8;因为最低位是 7 进制的,所以我们得到 1 和 1 个进位。第 2 位是:0 + 1 + 1(进位)= 2;因为此位是 2 进制的,所以我们得到 0 和 1 个进位。第 3 位是:2 + 4 + 1(进位)= 7;因为此位是 5 进制的,所以我们得到 2 和 1 个进位。第 4 位是:6 + 1(进位)= 7;因为此位是 10 进制的,所以我们就得到 7。最后我们得到:6203 + 415 = 7201。 输入格式: 输入首先在第一行给出一个 N 位的进制表(0 < N ≤ 20),以回车结束。 随后两行,每行给出一个不超过 N 位的非负的 PAT 数。 输出格式: 在一行中输出两个 PAT 数之和。 输入样例: 30527 06203 415 输出样例: 7201
AC代码:
#include <stdio.h> #include <string.h> int main() { int nBase, nA, nB, nS = 21, base, a, b; char sBase[21] = {0}, sA[21] = {0}, sB[21] = {0}, sSum[22] = {0}; // 读取三组数字,以字符串形式存储 scanf("%s %s %s", sBase, sA, sB); nBase = strlen(sBase); nA = strlen(sA); nB = strlen(sB); for(int i = 0; i < nBase; i++) { // 把数组 A B代表的数字转化为 整数 a, b // 此处用 nA,nB-i-1 控制每一组数的位置 [巧妙之处] a = nA <= i ? 0 : sA[nA - i - 1] - '0'; b = nB <= i ? 0 : sB[nB - i - 1] - '0'; // base代表该位置的进制 base = sBase[nBase - i - 1] == '0' ? 10 : sBase[nBase - i - 1] - '0'; // 运算每位的值 sSum[nS - i - 1] += a + b; // 计算进位与否 sSum[nS - i - 2] += sSum[nS - i - 1] / base; sSum[nS - i - 1] = sSum[nS - i - 1] % base; } // 变为字符类型 // 注 如果不经过 sSum[i] += '0' 变换,则字符存储是第一位' ',ASCII 编码为0 for(int i = 0; i < 21; i++) sSum[i] += '0'; // 保证第一位不为零 for(int first = 0; first < 21; first++) // 从前向后遍历,找到第一个不是0字符的数字 if(sSum[first] != '0') { // 输出第 first 位后的数字 puts(sSum + first); return 0; } // 若结果为0,则直接输出0 printf("0"); return 0; }
ASCII码附录:(from百度百科)
PAT_B_1077_互评成绩计算
题目描述:
在浙大的计算机专业课中,经常有互评分组报告这个环节。一个组上台介绍自己的工作,其他组在台下为其表现评分。最后这个组的互评成绩是这样计算的:所有其他组的评分中,去掉一个最高分和一个最低分,剩下的分数取平均分记为 G1 ;老师给这个组的评分记为 G2 。该组得分为 (G1 +G2 )/2,最后结果四舍五入后保留整数分。 本题就要求你写个程序帮助老师计算每个组的互评成绩。 输入格式: 输入第一行给出两个正整数 N(> 3)和 M,分别是分组数和满分,均不超过 100。随后 N 行,每行给出该组得到的 N 个分数(均保证为整型范围内的整数),其中第 1 个是老师给出的评分,后面 N−1 个是其他组给的评分。合法的输入应该是 [0,M] 区间内的整数,若不在合法区间内,则该分数须被忽略。题目保证老师的评分都是合法的,并且每个组至少会有 3 个来自同学的合法评分。 输出格式: 为每个组输出其最终得分。每个得分占一行。 输入样例: 6 50 42 49 49 35 38 41 36 51 50 28 -1 30 40 36 41 33 47 49 30 250 -25 27 45 31 48 0 0 50 50 1234 43 41 36 29 42 29 输出样例: 42 33 41 31 37 39
核心思路:
// 把成绩记录在Score[] 数组中,Score[0] 代表老师的打分 // 统计学生的有效成绩个数和最高最低分 // 最后运算的时候减去两个最值,有效成绩个数也要减去2 printf("%d\n",(int)(((((sum-min_s-max_s)*1.0/num)+Score[0])*1.0/2)+0.5));
AC代码:
// 1077 互评成绩计算 # include <stdio.h> # define Max 101 int main(void) { int N, len, num=0, i; int flag = -1; // flag标记为第一个有效的学生成绩 int M, sum=0, min_s, max_s; int Score[Max] = {0}; scanf("%d %d",&N,&M); len = N; while (len > 0) { sum = 0.0; num = 0; flag = -1; // 每次都设初值为-1 // 每组进行单独遍历,找出有效成绩个数,找到最大最小值 for (i=0; i<N; i++) { // Score[0]为老师评分,不参与G1计算 scanf("%d",&Score[i]); // 找到第一个有效的学生成绩 if (i>0 && flag==-1) { if (Score[i]>=0 && Score[i]<=M) flag = 0; } // 把找到的学生成绩记录为当前的最大最小值 if (0 == flag) { // 记录第一个有效的学生成绩 min_s = max_s = Score[i]; flag = 1; } // 统计有效分数 if (i>0 && Score[i]>=0 && Score[i]<=M) { sum += Score[i]; // 有效分数的个数 num++; // 更新最大最小值 if (Score[i] > max_s) max_s = Score[i]; if (Score[i] < min_s) min_s = Score[i]; } } num -= 2; // 总成绩计算 // 学生成绩为去掉最大最小值的平均值 // 总成绩为学生最终成绩和老师最终成绩均值 printf("%d\n",(int)(((((sum-min_s-max_s)*1.0/num)+Score[0])*1.0/2)+0.5)); len--; // 计算下一组 } return 0; }
PAT_B_1078 字符串压缩与解压
问题描述
文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。 例如 ccccc 就用 5c 来表示。如果字符没有重复,就原样输出。例如 aba 压缩后仍然是 aba。 解压方法就是反过来,把形如 5c 这样的表示恢复为 ccccc。 本题需要你根据压缩或解压的要求,对给定字符串进行处理。这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串。 输入格式: 输入第一行给出一个字符,如果是 C 就表示下面的字符串需要被压缩;如果是 D 就表示下面的字符串需要被解压。 第二行给出需要被压缩或解压的不超过 1000 个字符的字符串,以回车结尾。题目保证字符重复个数在整型范围内,且输出文件不超过 1MB。 输出格式: 根据要求压缩或解压字符串,并在一行中输出结果。 输入样例 1: C TTTTThhiiiis isssss a tesssst CAaaa as 输出样例 1: 5T2h4is i5s a3 te4st CA3a as 输入样例 2: D 5T2h4is i5s a3 te4st CA3a as10Z 输出样例 2: TTTTThhiiiis isssss a tesssst CAaaa asZZZZZZZZZZ
AC代码:
// PAT_1078_字符串压缩与解压 # include <stdio.h> # include <string.h> int main(void) { char ch[1010]; char Test; char a; int flag = 0; int sum = 0; // 记录字符的个数 int i = 0; // 控制ch 的变化 // 读入字符串 Test = getchar(); getchar(); gets(ch); while (ch[i] != '\0' && Test == 'D') { sum = 0; // 如果遇见数字,则转化为字符 if (ch[i]>='0' && ch[i]<='9') { sum = ch[i] - '0'; while (ch[i+1]>='0' && ch[i+1]<='9') { sum *= 10; i++; sum += ch[i] - '0'; } sum--; // 输出 while(sum != 0) { printf("%c",ch[i+1]); sum--; } } else { printf("%c",ch[i]); } i++; } while (ch[i] != '\0' && Test == 'C') { sum = 1; a = ch[i]; while (ch[i] == ch[i+1] && ch[i]!='\0') { sum++; i++; } if (1 != sum) printf("%d%c",sum,a); else printf("%c",a); i++; } return 0; }
PAT_B_1083_是否存在相等的差
题目描述:
给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差? 输入格式: 输入第一行给出一个正整数 N(2 ≤ N ≤ 10 000),随后一行给出 1 到 N 的一个洗牌后的排列,第 i 个数表示正面写了 i 的那张卡片背面的数字。 输出格式: 按照“差值 重复次数”的格式从大到小输出重复的差值及其重复的次数,每行输出一个结果。 输入样例: 8 3 5 8 6 2 1 4 7 输出样例: 5 2 3 3 2 2
要点反思:
注意:计算差val值时没有牺牲数组第一位即Diff[0], 则最后遍历Diff[]数组时不要忽略第一位!!!
AC代码:
// 1083 是否存在相等的差 # include <stdio.h> # include <math.h> # define Max 10001 int main(void) { int i, N, temp; int Diff[Max] = {0}; // 记录不同种类差的个数 int val = 0; // 求差 int max = 0; // 记录val的最大值 scanf("%d",&N); for(i=1; i<=N; i++) { scanf("%d",&temp); val = abs(temp - i); Diff[val]++; if (max < val) { max = val; } } // 倒序遍历到 Diff[0] for (i=max; i>=0; i--) { if (Diff[i] >= 2) { printf("%d %d\n",i,Diff[i]); } } return 0; }
PAT_B_1088_三人行
题目描述:
子曰:“三人行,必有我师焉。择其善者而从之,其不善者而改之。” 本题给定甲、乙、丙三个人的能力值关系为:甲的能力值确定是 2 位正整数;把甲的能力值的 2 个数字调换位置就是乙的能力值;甲乙两人能力差是丙的能力值的 X 倍;乙的能力值是丙的 Y 倍。请你指出谁比你强应“从之”,谁比你弱应“改之”。 输入格式: 输入在一行中给出三个数,依次为:M(你自己的能力值)、X 和 Y。三个数字均为不超过 1000 的正整数。 输出格式: 在一行中首先输出甲的能力值,随后依次输出甲、乙、丙三人与你的关系:如果其比你强,输出 Cong;平等则输出 Ping;比你弱则输出 Gai。其间以 1 个空格分隔,行首尾不得有多余空格。 注意:如果解不唯一,则以甲的最大解为准进行判断;如果解不存在,则输出 No Solution。 输入样例 1: 48 3 7 输出样例 1: 48 Ping Cong Gai 输入样例 2: 48 11 6 输出样例 2: No Solution
思路整理:
倒序遍历甲(99-10),找到第一个符合题目要求的解 丙不一定是整数,设为double类型
AC代码:
// 1088 三人行 # include <stdio.h> # include <math.h> // 输出甲乙丙与自己的数值关系 void print(int , double ); int main(void) { int M,A,B; // 分别表示自己和甲乙 double C; // 丙不一定是整数 int X,Y; int flag = 0; // 有无解的标志位 scanf("%d %d %d",&M, &X, &Y); for (A = 99; A >= 10; A--) { // 计算乙的值B B = (A%10)*10 + A/10; C = abs(A-B) * 1.0/X; if (B == C*Y) { flag = 1; break; } } // 如果有解,则按照规则输出 if (1 == flag) { printf("%d",A); print(M,A); print(M,B); print(M,C); } // 否则输出无解 else { printf("No Solution\n"); } return 0; } void print(int M, double N) { if (M == N) printf(" Ping"); else if (M < N) printf(" Cong"); else printf(" Gai"); }
PAT_B_1092 最好吃的月饼
题目描述:
月饼是久负盛名的中国传统糕点之一,自唐朝以来,已经发展出几百品种。 若想评比出一种“最好吃”的月饼,那势必在吃货界引发一场腥风血雨…… 在这里我们用数字说话,给出全国各地各种月饼的销量,要求你从中找出销量冠军,认定为最好吃的月饼。 输入格式: 输入首先给出两个正整数 N(≤1000)和 M(≤100),分别为月饼的种类数(于是默认月饼种类从 1 到 N 编号)和参与统计的城市数量。 接下来 M 行,每行给出 N 个非负整数(均不超过 1 百万),其中第 i 个整数为第 i 种月饼的销量(块)。数字间以空格分隔。 输出格式: 在第一行中输出最大销量,第二行输出销量最大的月饼的种类编号。如果冠军不唯一,则按编号递增顺序输出并列冠军。数字间以 1 个空格分隔,行首尾不得有多余空格。 输入样例: 5 3 1001 992 0 233 6 8 0 2018 0 2008 36 18 0 1024 4 输出样例: 2018 3 5
要点反思:
int max,flag=0; // 分别记录最大值和 标志位 // 标志位作用是 当读取到最大值时,第一个最大值前不用空格 // 保证题目 行末无多余空格 // 不用计算满足题目条件的max值数量
AC代码:
// 1092 最好吃的月饼03 AC // 标志位作用是 当读取到最大值时,第一个最大值前不用空格 // 保证题目 行末无多余空格 // 不用计算满足题目条件的max值数量 # include <stdio.h> # define Max 1000001 int main(void) { int N, M, val; int i, j; int max,flag=0; // 分别记录最大值和 标志位 // 标志位作用是 当读取到最大值时,第一个最大值前不用空格 // 保证题目 行末无多余空格 // 不用计算满足题目条件的max值数量 int Sum[Max] = {0}; scanf("%d %d",&N, &M); // 计算每种的销量 for (i=0; i<M; i++) { for (j=0; j<N; j++) { scanf("%d",&val); Sum[j] += val; } } max = Sum[0]; for (i=0; i<N; i++) { // 计算最大值的数值 if (max < Sum[i]) { max = Sum[i]; } } // 输出最终结果 printf("%d\n",max); for(i=0; i<N; i++) { if (Sum[i]==max) { // 通过标志位flag 控制输出格式 if(0 == flag) { flag = 1; } else { printf(" "); } printf("%d",i+1); } } return 0; }
RRR