CSP 复赛模拟赛后补题报告

  日期:2023年10月1日星期日
  学号:S14029
  姓名:黄子航
    1. 比赛概况:
  比赛总分共 4 题,满分 400,赛时拿到190 分,其中第一题 90 分,第二题
  70 分,第三题 20 分,第四题 10 分。
    2. 比赛过程:
  比赛时按照顺序做的,第一题一开始是暴力求解,后来发现规律,但是优化没做好,直接做下一题了,
第二题也是没优化好,时间超限了,第三题一开始暴力求解,做了一半发现了问题,就开始优化,但是因
为题目理解有些小问题导致丢了很多分。第四题思路卡在一个地方,一直没有想通,最后还是个半成品,
因为时间原因不得不提交了。
    3. 题解报告:
    (1) 第一题:数字降级
  情况:赛中90分,已补题。
  题意:数字的每一次降级都代表该数字除以一个自己的因子,求最少几次操作后,该数字会变为质数。
  赛时本题做题想法:一个数是质数就不用操作,不是质数只要操作一次,所以只需要判断该数是不是质
数即可,但是由于优化没做好,在数据增大时时间超限,因此只拿了90分。
  题解:通过模运算求质数,再分别判断进行输出。
  AC 代码:
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
    freopen("down.in","r",stdin);
    freopen("down.out","w",stdout);
    long long n;
    cin>>n;
    for(int i=2;i<=n/i;i++){
        if(n%i==0){
            cout<<1;
            fclose(stdin);
            fclose(stdout);
            return 0;
        }
    }
    cout<<0;
    fclose(stdin);
    fclose(stdout);
    return 0;
}
    (2) 第二题:分组
  情况:赛中70分,已补题。
  题意:一些人来做游戏,每人都有一个自己的自然数分数,一些人组成一个小组,小组也有自己的小组
分数,小组分数是除组员分数外最小的自然数,求小组分数和最大是多少。
  赛时本题做题想法:对分数的数组进行多次遍历,从0开始一个一个找自然数,找到一个就加一。
  题解:使用桶来做,使用min函数来找到所有自然数中最少的那一个,就是总分,
  AC 代码:
#include<iostream>
#include<cstdio>
using namespace std;
int gr[1005];
int main(){
    freopen("group.in","r",stdin);
    freopen("group.out","w",stdout);
    int n,m=0;
    cin>>n;
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        gr[x]++;
    }
    int minn=gr[0],cnt=minn;
    for(int i=1;i<=1000;i++){
        minn=min(minn,gr[i]);
        cnt+=minn;
    }
    cout<<cnt;
    fclose(stdin);
    fclose(stdout);
    return 0;
}
(3) 第三题:抢夺地盘
  情况:赛中20分,已补题。
  题意:一人在游戏中有编号为1~n的n个城镇,每个城镇都有战斗力和钱数,他将钱数最多的城镇放在中
部,其他城镇则是越靠近钱数最多的城镇,钱数就越多,如果有一个城镇因钱数少而被分到了外侧,战斗
力却比更靠内侧的高,就会发生矛盾,求最少调整多少次战力可以不发生矛盾。
  赛时本题做题想法:两两对比,进行调整,最后输出次数。
  题解:使用dp来做,前半段用不降序子排列,后半段用不升序子排序,最后输出即可。
  AC 代码:
#include<bits/stdc++.h>
using namespace std;
int a[100010], b[100010], c[100010];
int n, p, s;
int main(){
    freopen("seize.in","r",stdin);
    freopen("seize.out","w",stdout);
    cin >> n >> s;
    for(int i=1; i<=n; i++) cin >> a[i];
    b[++p]=a[1];
    for(int i=2; i<s; i++){
        if(a[i]>=b[p]){
            b[++p]=a[i];
        }
        else{
            int l = 1, r = p, mid = p >> 1;
            while(l != r){
                if(a[i] < b[mid]) r = mid;
                else l = mid + 1;
                mid = (l+r) >> 1;
            }
            b[l] = a[i];
        }
    }
    if(a[s]>=b[p]){
        p++;
    }
    else{
        a[s]=10000000000;
    }
    int ans=s-p;
    p=1;
    c[p]=a[s];
    for(int i=s+1; i<=n; i++){
        if(a[i]<=c[p]) c[++p]=a[i];
        else{
            int l = 1, r = p, mid = p >> 1;
            while(l != r){
                if(a[i] > c[mid]) r = mid;
                else l = mid + 1;
                mid = (l + r) >> 1;
            }
            c[l] = a[i];
        }
    }
    ans+=(n-s+1)-p;
    cout << ans;
    fclose(stdin);
    fclose(stdout);
    return 0;
}
(4) 第四题:闯关
情况:赛中10分。
题意:两人共同去闯关,可以一次越过n,并且两人有一件神器,可以一次越过m,两人不可串跑道,但
可以在距离不超过q时传递神器,请问两人最少传递多少次神器后可以都到达终点?
赛时本题做题想法:本来是想用贪心算法来做的,但是代码编不出来,改代码时时间就结束了,只交了
一个半成品,所以只有10分。
题解:使用贪心算法或dp算法,贪心算法主要是求局部最优解,以求整体最优解,放在此题中就是一人
在把神器传给另一人时,要走得尽量远。
AC 代码:
#include <iostream>
using namespace std;
int n,m,k,q,f,qa,qb,ans;
int a[10005],b[10005];
int main() {
    cin>>n>>m>>k>>q;
    for(int i=1;i<=n;i++)    cin>>a[i];
    for(int i=1;i<=n;i++)    cin>>b[i];
    while(1){
        if(!f){
            while(b[qb+1]-b[qb]<=m&&qb+1<=n)    qb++;
            if(qb==n)    break;
            while(a[qa+1]-b[qb]<=q&&qa+1<=n)    qa++;
            ans++; 
            f=1;
            if(qa==n)    break;
        }else{
            while(a[qa+1]-a[qa]<=m&&qa+1<=n)    qa++;
            if(qa==n)    break;
            while(b[qb+1]-a[qa]<=q&&qb+1<=n)    qb++;
            ans++;
            f=0;
            if(qb==n)    break;
        }
    }
    cout<<ans;
    return 0;
}
4. 赛后总结:
本次比赛由于时间不足,知识不够充分,编程能力较弱的原因导致分数较低,我应该多做练习,管理好时
间,下次避免出现此类的错误。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值