2021PAT春季赛 试做

题1

题意:求在给定上界范围内,公差最大的且都为素数的,等差数列。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;

int n, m;
bool isPrime[N];
vector<int> primes, ans;

bool is_prime(int x){
    if(x<2){
        return false;
    }
    for(int i = 2;i<=sqrt(x);i++){
        if(x%i==0){
            return false;
        }
    }
    return true;
}

// 统计不大于m的素数
void init(){
    for(int i = 2;i<=m;++i){
        isPrime[i] = is_prime(i);
        if(isPrime[i]){
            primes.push_back(i);
        }
    }
}

//判断是否存在n个数满足公差为d的等差数列
// 优先达成首项最大
bool judge(int x,int d,int cnt){
    if(!isPrime[x]||x<2){
        return false;
    }
    if(cnt<=1){
        return true;
    }
    return judge(x-d, d, cnt-1);
}

int main(){
    cin>>n>>m;
    init();

    int mPrime = primes.back();//最大素数
    bool flag = false;

    if(n==1){// n为1输出最大素数
        cout<<mPrime<<endl;
        return 0;
    }

    for(int d = (mPrime-2)/(n-1);d>=1 && !flag;d--){//逐步减少差值
        for(int k = primes.size() - 1;primes[k]-(n-1)*d>=2;k--){//尝试每一个素数
            if(judge(primes[k], d, n)){
                flag = true;
                for(int i = 0;i<n;++i){
                    ans.push_back(primes[k]-i*d);
                }
                reverse(ans.begin(), ans.end());//题意要求从小到大输出
                break;
            }
        }
    }

    if(flag){
        for(int i = 0;i<n;++i){
            cout<<ans[i]<<(i==n-1?'\n':' ');
        }
    }else{// 找不到对应的等差数列
        cout<<mPrime<<endl;
    }
}

参考:AcWing

题2

题意:给出一天内n个人进出实验室的时间,在保证同一时刻实验室只能有一人工作的情况下(前一人离开的时间可以和后一人进入的时间相同),求这天最多可以让几个人进入实验室工作。
思路:将所有时间换算成秒为单位的整数,然后按照出实验室的时间递增进行排序即可。
C++

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 2e3+5;
struct Node{
    int st, en;
}per[N];

int gettime(int hh, int mm, int ss){
    return hh*60*60 + mm*60 + ss;
}

bool cmp(const Node &a,const Node &b){
    if(a.en==b.en) return a.st<b.st;
    return a.en<b.en;
}

int main(){
    int n;
    scanf("%d",&n);

    for(int i = 0;i<n;++i){
        int hh, mm, ss;
        scanf("%d:%d:%d", &hh, &mm, &ss);
        per[i].st = gettime(hh,mm,ss);

        scanf("%d:%d:%d",&hh,&mm,&ss);
        per[i].en = gettime(hh,mm,ss);
    }

    sort(per,per+n,cmp);

    int ans = 0;
    for(int i = 0;i<n;++i){
        int pre = per[i].en, cnt = 1;

        [for(int j = i + 1;j<n;++j){//找到一个](https://blog.csdn.net/Ai_Mijie/article/details/114750979)
            if(per[j].st>=pre){
                cnt++;
                pre = per[j].en;
            }
        }
        ans = max(ans, cnt);
    }

    printf("%d\n",ans);
    return 0;
}

题三

题意:首先将给出的n个数字按照输入顺序构造一个大顶堆,然后依次判断给出的m个询问是否正确。询问内容包括:a是否为根、a和b是否为兄弟节点、a是否为b的左子节点,a是否为b的右子节点、a是否为b的父节点。
思路:从无到有构造大顶堆,其在任何时刻都满足完全二叉树,因此可以使用数组来存树,即根节点的下标为1,第i个节点的左子节点下标为i<<1,右子节点下标为i<<1|1,然后对于每次插入逐层更新到根节点即可。由于询问给出的是每个节点的值,因此在最大堆生成后,可以使用一个map来记录每个节点的值与其下标的映射关系。最后按照询问内容,进行判断即可。
题目不完整,略过

题四

不完整 略过
参考:参考

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值