日期: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. 赛后总结:
本次比赛由于时间不足,知识不够充分,编程能力较弱的原因导致分数较低,我应该多做练习,管理好时
间,下次避免出现此类的错误。
CSP 复赛模拟赛后补题报告
最新推荐文章于 2024-09-12 11:35:40 发布