PAT (Basic Level) Practice - II 1101-1125(已更新至最新!)
更多详见>>
OJ题解系列 目录导航帖
题目传送门
序
这里是PAT乙级考试真题的第二部分(1101-1125)
首先总结一下PAT乙级考试的常考内容:
1.模拟:根据题目的描述/步骤,模拟题目的步骤编写算法
2.程序结构类:考察分支、循环、选择语句,如分段函数、分段计价、遍历数组
3.基础算法类:贪心、数论、枚举、排序等,一般情况下主要考察这几类,难度不会特别大,需注意算法的细节,对特殊数据的处理。
4.基础数据结构:主要就两种——数组和链表(静态或动态)、栈和队列
5.C++的STL模板类:简单了解stack,queue,priority_queue,map,vector,string,pair的用法
接下来就是题解部分了,每道算法题都标注有对应的算法标签,对于那些易错、较难或是测试点比较特殊的题目会着重标注,本章推荐的题目有:
1104 天长地久 (20 分) | 数论 + 枚举 |
---|---|
1109 擅长C (20 分) | 字符串 + 模拟 |
1115 裁判机(25分) | 模拟 |
1123 舍入 (20 分) | 字符串 + 输入/输出格式 |
最后,希望大家都能在PAT乙级考试中取得自己理想的成绩!
1101 B是A的多少倍 (15 分)
算法标签: 模拟
注意点: 截取D位,拼接到高位,然后将高位的数字移动到低位,新数除以原数,可得结果
#include<bits/stdc++.h>
using namespace std;
int main(){
int A;
int D;
scanf("%d%d",&A,&D);
int A1 = A;
int cnt1 = 0;
while(A1){
A1/=10;
cnt1++;
}
D = D % cnt1;
if(D==0){
printf("1.00\n");
return 0;
}
int cnt2 = 1;
for(int i=0;i<D;i++){
cnt2 *= 10;
}
A1 = 1;
for(int i=0;i<cnt1-D;i++){
A1 = A1*10;
}
A1 = (A%cnt2)*A1;
A1 += (A/cnt2);
double res = 1.0*A1/(1.0*A);
printf("%.2lf\n",res);
return 0;
}
1102 教超冠军卷 (20 分)
算法标签: 排序
注意点: 遍历每条信息,记录销售量和销售额的最大值及ID号,输出结果
#include<bits/stdc++.h>
using namespace std;
char s1[20];
char s2[20];
int max_sale = -1;
int max_amount = -1;
int main(){
int N;
scanf("%d",&N);
for(int i=0;i<N;i++){
char s[20];
scanf("%s",s);
int sale,amount;
scanf("%d%d",&sale,&amount);
if(sale*amount>max_sale){
max_sale = sale*amount;
strcpy(s1,s);
}
if(amount>max_amount){
max_amount = amount;
strcpy(s2,s);
}
}
printf("%s %d\n",s2,max_amount);
printf("%s %d\n",s1,max_sale);
return 0;
}
1103 缘分数 (20 分)
算法标签: 枚举法
注意点: 枚举所有可能的数A和B,若满足题目中的条件,就输出结果
#include<bits/stdc++.h>
using namespace std;
int res1[10005];
int res2[10005];
int cnt = 0;
int main(){
int m,n;
scanf("%d%d",&m,&n);
for(int a=m;a<=n;a++){
for(int b=2;b<=sqrt(2*a);b++){
if(a*a*a-(a-1)*(a-1)*(a-1) == (b*b+(b-1)*(b-1))*(b*b+(b-1)*(b-1))){
res1[cnt] = a;
res2[cnt++] = b;
}
}
}
if(cnt){
for(int i=0;i<cnt;i++){
printf("%d %d\n",res1[i],res2[i]);
}
}else{
printf("No Solution\n");
}
return 0;
}
1104 天长地久 (20 分)
算法标签: 数论 + 枚举法
注意点: 本题很棒,值得反复练习
m 与 n 的最大公约数是一个大于 2 的素数,意味着m只能是末尾带有9的数字,否则不满足最大公约数>2,如gcd(15,16)=1,因此只要从末尾9的个数出发,依次枚举即可得到结果,最后排序输出。
#include<iostream>
#include<math.h>
#include<string>
using namespace std;
int isPrime(int n) {
if (n <= 1)
return 0;
for (int i = 2; i <= sqrt(n); i++) {
if (n%i == 0)
return 0;
}
return 1;
}
int gcd(int a, int b) {
if (b == 0)
return a;
else
return gcd(b, a%b);
}
int digit(int n) {
string a = to_string(n);
int sum = 0;
for (int i = 0; i < a.length(); i++) {
sum = sum + a[i] - '0';
}
return sum;
}
int find_min(int nine, int k) {
string a;
for (int i = 0; i < k; i++) {
if (i == 0)
a = "1";
else
a += "0";
}
for (int i = k - 1; i >= k - nine; i--)
a[i] = '9';
return stoi(a);
}
int Hash[200];
int main() {
int n;
scanf("%d", &n);
int k, m;
int com;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &k, &m);
printf("Case %d\n", i);
int flag = 0;
if (m <= 9 * k) {
for (int j = 3; j < m; j++) {
int d = gcd(j, m);
if (isPrime(d) && d > 2) {
if ((m - j + 1) % 9 == 0) {
int nine = (m - j + 1) / 9;
int least = find_min(nine, k);
int maxn = pow(10, k);
for (int t = least; t < maxn; t+=pow(10,nine) ){
if (digit(t) == m && digit(t + 1) == j) {
flag = 1;
printf("%d %d\n", j, t);
}
}
}
}
}
}
if (flag == 0)
printf("No Solution\n");
}
return 0;
}
1105 链表合并 (25 分)
算法标签: 链表 + 模拟
注意点: 此类题目可用数组模拟静态链表,遍历链表是常考点。每隔2个数合并A,每隔一个数合并B,直到链表末尾
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
map<int,int> next1;
map<int,int> value1;
int a_value[maxn];
int a_add[maxn];
int b_value[maxn];
int b_add[maxn];
int change[maxn];
int cnt1 = 0;
int cnt2 = 0;
int main(){
int start_s1,start_s2;
int N;
scanf("%d%d%d",&start_s1,&start_s2,&N);
for(int i=0;i<N;i++){
int add,data,next;
scanf("%d%d%d",&add,&data,&next);
next1[add] = next;
value1[add] = data;
}
int s1 = start_s1;
while(s1!=-1){
a_add[cnt1] = s1;
a_value[cnt1++] = value1[s1];
s1 = next1[s1];
}
int s2 = start_s2;
while(s2!=-1){
b_add[cnt2] = s2;
b_value[cnt2++] = value1[s2];
s2 = next1[s2];
}
if(cnt1>cnt2){
reverse(b_add,b_add+cnt2);
reverse(b_value,b_value+cnt2);
}else{
reverse(a_add,a_add+cnt1);
reverse(a_value,a_value+cnt1);
for(int i=0;i<cnt1;i++){
change[i] = a_add[i];
}
for(int i=0;i<cnt2;i++){
a_add[i] = b_add[i];
}
for(int i=0;i<cnt1;i++){
b_add[i] = change[i];
}
for(int i=0;i<cnt1;i++){
change[i] = a_value[i];
}
for(int i=0;i<cnt2;i++){
a_value[i] = b_value[i];
}
for(int i=0;i<cnt1;i++){
b_value[i] = change[i];
}
swap(cnt1,cnt2);
}
int i = 0;
int j = 0;
if(cnt1==2*(cnt2)){
while(i<cnt1 && j<cnt2){
if(j!=cnt2-1){
printf("%05d %d %05d\n",a_add[i],a_value[i],a_add[i+1]);
i++;
printf("%05d %d %05d\n",a_add[i],a_value[i],b_add[j]);
i++;
printf("%05d %d %05d\n",b_add[j],b_value[j],a_add[i]);
j++;
}else{
printf("%05d %d %05d\n",a_add[i],a_value[i],a_add[i+1]);
i++;
printf("%05d %d %05d\n",a_add[i],a_value[i],b_add[j]);
i++;
printf("%05d %d %d\n",b_add[j],b_value[j],-1);
j++;
}
}
}else{
while(i<cnt1 && j<cnt2){
if(j!=cnt2-1){
printf("%05d %d %05d\n",a_add[i],a_value[i],a_add[i+1]);
i++;
printf("%05d %d %05d\n",a_add[i],a_value[i],b_add[j]);
i++;
printf("%05d %d %05d\n",b_add[j],b_value[j],a_add[i]);
j++;
}else{
printf("%05d %d %05d\n",a_add[i],a_value[i],a_add[i+1]);
i++;
printf("%05d %d %05d\n",a_add[i],a_value[i],b_add[j]);
i++;
printf("%05d %d %05d\n",b_add[j]</