PAT 甲级-入门模拟

阅读原文

当时准备 PAT 竞赛时候,买了本《算法笔记》,书中将题型进行分类,是我最系统的一次算法学习,对题型判断、解题思路都有了新的认知,本篇文章主要记录当时刷的入门模拟题,算是比较简单的算法题(有些都不能称之为算法),就当是打基础了

包括分类:简单模拟查找元素图形输出日期处理进制转换字符串处理

简单模拟

思想解释

根据题目的要求去做即可,主要考察代码的编写能力

类型练习

1042

题目:Shuffling Machine

Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid “inside jobs” where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.

The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:

S1, S2, …, S13, H1, H2, …, H13, C1, C2, …, C13, D1, D2, …, D13, J1, J2

where “S” stands for “Spade”, “H” for “Heart”, “C” for “Club”, “D” for “Diamond”, and “J” for “Joker”. A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer K (<= 20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.

Sample Input:

2
36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47

Sample Output:

S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5

思路: 用字符串不如使用整型数组直接进行循环调换,根据其编号输出对应的花色

  • 建立三个整型数组,分别用来存储初始顺序、洗牌后的顺序、洗牌规则

  • 每次洗牌就是将规则数组中的当前数字作为下标用来控制洗牌后的数组被赋值洗牌前的编号

  • 最后花色和数值的输出需要对编号进行-1,这样是为了防止 13、26…这样的边界数字越界的情况,但输出数值时需要再+1

代码:

#include <cstdio>

int main()
{

    int times;
    scanf("%d", &times); //输入洗牌几次
    int start[55], end[55], order[55];
    for (int i = 1; i < 55; i++)
    {
        scanf("%d", &order[i]); //输入洗牌规则
        start[i] = i;           //初始化默认排序
    }
    for (int i = 0; i < times; i++)
    {
        for (int j = 1; j < 55; j++)
        {
            end[order[j]] = start[j]; //根据规则洗牌
        }
        for (int k = 1; k < 55; k++)
        {
            start[k] = end[k]; //将每次洗完的牌放到初始数组,为下一次洗牌做准备
        }
    }
    char color[5] = {'S', 'H', 'C', 'D', 'J'}; //字符花色数组
    for (int i = 1; i < 55; i++)
    {
        end[i]--;
        //每次的序号都要自减,防止 13、26…这样的数字除和摸出 13 时得到的值不符合逻辑
        printf("%c%d", color[end[i] / 13], end[i] % 13 + 1);
        if (i != 54)
        { //避免额外空格
            printf(" ");
        }
    }
    return 0;

}

1046

题目:Shortest Distance

The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

Input Specification:

Each input file contains one test case. For each case, the first line contains an integer N (in [3, 1 0 5 10^5 105]), followed by N integer distances D1 D2 ⋯ DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (≤ 1 0 4 10^4 104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 1 0 7 10^7 107.

Output Specification:

For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

Sample Input:

5 1 2 4 14 9
3
1 3
2 5
4 1

Sample Output:

3
10
7

思路: 实际上只有一条循环线路,只要求出单个方向(如顺时针)的值,用距离总和减去后获得反向距离,返回二者最小值

  • 创建一个距离数组distance[],其中distance[i]中保存的是从 V1 点到 Vi+1 的距离,在输入时就将数组和距离总和记录下来减少复杂度

  • 输入的起点 begin 和终点 end 之间的顺时针距离 dis_left 为 dis_left=distance[end-1]-distance[begin-1],需要判断 begin 与 end 的大小关系,始终保持小的在前

代码:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int n;
    scanf("%d", &n);
    vector<int> dis(n + 1); //动态数组分配空间后所有的值为 0
    int sum = 0, left, right;
    for (int i = 1; i <= n; i++)
    {
        int temp;
        scanf("%d", &temp);
        sum += temp;
        dis[i] = sum; //距离数组保存的是 V1 到 Vi 的顺时针距离
    }
    int cnt;
    scanf("%d", &cnt); //输入判断几对
    for (int i = 0; i < cnt; i++)
    {
        scanf("%d %d", &left, &right);
        if (left > right) //始终保持顺时针判断
            swap(left, right);
        int temp = dis[right - 1] - dis[left - 1];
        printf("%d\n", min(temp, sum - temp));
    }
    system("pause");
    return 0;
}
1065

题目:A+B and C (64bit)

Given three integers A, B and C in [− 2 63 2^{63} 263, 2 63 2^{63} 263),you are supposed to tell whether A+B>C.

Input Specification:

The first line of the input gives the positive number of test cases, T (≤10). Then T test cases follow, each consists of a single line containing three integers A, B and C, separated by single spaces.

Output Specification:

For each test case, output in one line Case #X: true if A+B>C, or Case #X: false otherwise, where X is the case number (starting from 1).

Sample Input:

3
1 2 3
2 3 4
9223372036854775807 -9223372036854775808 0

Sample Output:

Case #1: false
Case #2: true
Case #3: false

思路: 数据类型过大用 long long 型进行存储,同时需要考虑溢出的情况(同为正值溢出必大于,同为负值溢出必小于)

  • 因为 A、B 的大小为 [-2^63, 2^63),用 long long 存储 A 和 B 的值,以及他们相加的值 sum

  • 如果 A > 0, B < 0 或者 A < 0, B > 0,sum 是不可能溢出的

  • 如果 A > 0, B > 0,sum 可能会溢出,sum 范围理应为 (0, 2^64 – 2],溢出得到的结果应该是 [-2^63, -2] 是个负数,所以 sum < 0 时候说明溢出了

  • 如果 A < 0, B < 0,sum 可能会溢出,同理,sum 溢出后结果是大于 0 的,所以 sum > 0 说明溢出了

代码:

#include <cstdio>
#include <cstdlib>

int main()
{

    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        long long a, b, c;
        scanf("%lld %lld %lld", &a, &b, &c);
        long long sum = a + b;
        if (a > 0 && b > 0 && sum < 0)
        { //正溢出,结果必定大于 C
            printf("Case #%d: true\n", i + 1);
        }
        else if (a < 0 && b < 0 && sum >= 0)
        { //负溢出,两个负数相加而且溢出,必小于 C
            printf("Case #%d: false\n", i + 1);
        }
        else if (sum > c) //无溢出,正常比较
        {
            printf("Case #%d: true\n", i + 1);
        }
        else
        {
            printf("Case #%d: false\n", i + 1);
        }
    }
    system("pause");
    return 0;

}

1002

题目:A+B for Polynomials

This time, you are supposed to find A+B where A and B are two polynomials.

Input Specification:

Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:

K N1 aN1 N2 aN2 … NK aNK

where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤K≤10,0≤NK<⋯< N2<N1≤1000.

Output Specification:

For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.

Sample Input:

2 1 2.4 0 3.2
2 2 1.5 1 0.5

Sample Output:

3 2 1.5 1 2.9 0 3.2

思路: 使用浮点数组用指数作为下标,存储系数的值,只要指数相同就为同一项,系数直接相加即可

  • 数组长度为指数的最大值 1000,poly[i] = j表示指数 i 的系数为 j,接收 exponent 和 coefficient 输入的同时将对应指数的系数加入到 poly 数组中,所有非零系数的个数,然后从前往后输出所有系数不为 0 的指数和系数

  • 注意输出格式和输出的精度

代码:

#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std;

int main()
{
    vector<double> coef(1001, 0); //根据数据规模,创建浮点数组存储系数
    int cnt = 0;                  //判断最后有多少项
    int m, n;                     //获取每行有多少项
    scanf("%d", &m);
    for (int j = 0; j < m; j++)
    {
        int e_temp;
        double c_temp;
        scanf("%d %lf", &e_temp, &c_temp); //根据项数输入指数和系数
        coef[e_temp] += c_temp;            //用指数作为下标将系数相加
    }
    scanf("%d", &n);
    for (int j = 0; j < n; j++)
    {
        int e_temp;
        double c_temp;
        scanf("%d %lf", &e_temp, &c_temp);
        coef[e_temp] += c_temp;
    }
    for (int i = 0; i < coef.size(); i++)
    {
        if (coef[i])
        { //记录所有不为 0 的项
            cnt++;
        }
    }
    printf("%d", cnt);
    for (int i = 1000; i >= 0; i--)
    {
        if (coef[i])
        { //不为 0 便输出指数和系数,注意空格和小数点为 1 位
            printf(" %d %.1f", i, coef[i]);
        }
    }
    system("pause");
    return 0;
}
1009

题目:Product of Polynomials

This time, you are supposed to find A×B where A and B are two polynomials.

Input Specification:

Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:

K N1 aN1 N2 aN2 … NK aNK

where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1, 2, ⋯, K) are the exponents and coefficients, respectively. It is given that 1≤K≤10, 0≤NK<⋯<N2<N1≤1000.

Output Specification:

For each test case you should output the product of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate up to 1 decimal place.

Sample Input:

2 1 2.4 0 3.2
2 2 1.5 1 0.5

Sample Output:

3 3 3.6 2 6.0 1 1.6

思路: 建立两个数组,一个保存第一行的多项式,一个在第二行读入时,直接循环第一个数组的内容进行处理存储

  • 因为是乘法,根据最大指数为 1000,那么乘积的最大指数就是 2000,所以 ans 数组的数据规模为 2001

  • 无需将两个多项式分别保存完再处理,在输入第二个多项式时直接循环与第一个多项式的每一项相乘即可(只算非零)

代码:

#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std; 

int main()
{

    vector<double> coef(1001, 0);
    vector<double> ans(2001, 0); //根据指数最大为 1000,相乘后最大的指数为 1000+1000
    int cnt = 0;
    int m, n;
    scanf("%d", &m);
    for (int j = 0; j < m; j++)
    {
        int e_temp;
        double c_temp;
        scanf("%d %lf", &e_temp, &c_temp);
        coef[e_temp] += c_temp;
    }
    scanf("%d", &n);
    for (int j = 0; j < n; j++)
    {
        int e_temp;
        double c_temp;
        scanf("%d %lf", &e_temp, &c_temp);
        for (int i = 0; i < coef.size(); i++)
        { //在第二行每输入一项,就与第一行的每项相乘,得到的值根据相同指数加到 ans 数组中
            if (coef[i])
            {
                ans[i + e_temp] += coef[i] * c_temp;
            }
        }
    }
    for (int i = 0; i < ans.size(); i++)
    {
        if (ans[i])
        {
            cnt++;
        }
    }
    printf("%d", cnt);
    for (int i = 2000; i >= 0; i--)
    {
        if (ans[i])
        {
            printf(" %d %.1f", i, ans[i]);
        }
    }
    system("pause");
    return 0;

}

查找元素

思想解释

在一组给定的元素中查找目标元素,范围较小可直接遍历查找,或者使用某些数据类型自带的 find() 函数,查找最大最小值可以使用 [algorithm] 下的 max_elemen() 函数等

二分查找

有些元素的数据范围较大,采用遍历消耗的时间难免过多,所以采用二分查找的方式能够用较小的时间复杂度来完成

具体思路就是每次确定中值mid=(left+right)/2,用要查询的数 x 与 mid 进行比较,根据大小关系再与另一半进行比较,值得注意的是,有些数据范围实在是太大导致 left+right 的值就已经超过的 int 支持的数据范围,这时可以使用mid=left+(right-left)/2
在 [algorithm] 下的模板函数为:binary_search(first,last,val)

类型练习

1011

题目:World Cup Betting

With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excited as the best players from the best teams doing battles for the World Cup trophy in South Africa. Similarly, football betting fans were putting their money where their mouths were, by laying all manner of World Cup bets.

Chinese Football Lottery provided a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值