官方题解 | 欢乐赛#58题解
2025-10-20 13:51:02
发布于:浙江
赛纲介绍
本次题目的总体题目难度如下,各位选手可以借此评估一下自身的技术水平。
| 题目编号 | 题目名称 | 题目难度 | 
|---|---|---|
| T1 | 音频计算 | 入门 | 
| T2 | 排队时间 | 入门 | 
| T3 | 作业检查 | 入门 | 
| T4 | 立体炸弹 | 入门 | 
| T5 | 三好学生 | 普及- | 
| T6 | 产量预测 | 普及- | 
T1 音频计算
题目大意
题目给出了关于音频文件大小的计算方法和文件大小单位的转换规则,这里读题时注意采样频率的 是单位,按照提示中的计算公式计算时并不会影响结果。
题解思路
本题本质为格式化输入输出,按照提示的公式计算后进行单位转换即可,注意使用 double 类型进行计算,输出要使用 printf 方法保留  位小数。
误差不到 的结果均视为正确。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    double t,x,y,z;
    cin>>t>>x>>y>>z;
    double ans=1.0*x*y/8*z*t/1024/1024;
    printf("%.4lf\n",ans);
    return 0;
}
T2 排队时间
题目大意
题目给出了 位患者的等待时间,然后才给出当前刚轮到的患者序号 和阿北的序号 ,要求求出所需的等待时间。
题解思路
本题本质为一维数组的使用,按照题目要求循环遍历序号在 之间的每个数组元素进行统计即可。根据题目描述,这里包含序号 但不包含序号 。
由于序号输入是后置的,所以数据输入必须存储于数组中,在先给出编号的题目中也可以直接进行统计。
这里求区间和的要求也可以考虑使用前缀和的模版代码实现。
参考代码
#include <bits/stdc++.h>
using namespace std;
int a[310];
int main() {
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int x,y;
    cin>>x>>y;
    int ans=0;
    for(int i=x;i<y;i++){
        ans=ans+a[i];
    }
    cout<<ans<<endl;
    return 0;
}
T3 作业检查
题目大意
题目给出了一个标准字符串和多个待检查的字符串,要求按顺序找出有错误的字符串并标出错误位置。
题解思路
本题本质为字符串的遍历,由于可能存在多个错误位置,所以直接遍历整个字符串进行对比即可。注意要标记一下每位同学是否出错,第一次发现出错时要先输出当前同学编号,后续发现错误时只需要输出位置即可。题目描述中对缺少字符和多余字符的位置也视为错误,需要注意循环条件。
字符串的题目在输入部分要检查是否正确输入,尤其需要关注数输入后的空格和换行符,检查后续的字符串输入是否正确进行。
参考代码
#include <bits/stdc++.h>
using namespace std;
string s;
string st[110];
int main() {
	int n;
	cin>>n;
	getchar();//消除换行符
	getline(cin,s);
	s=" "+s;//字符串默认下标0开始,加上空格后内容从下标1开始
	int slen=s.size();
	for(int i=1;i<=n;i++){
		getline(cin,st[i]);
		st[i]=" "+st[i];
	}
	for(int i=1;i<=n;i++){
		int stlen=st[i].size();
		int flag=1;
		for(int j=1;j<slen||j<stlen;j++){//注意缺少字符和多余字符的情况
			if(j>=slen||j>=stlen){
				if(flag==1){
					flag=0;
					cout<<i;
				}
				cout<<" "<<j;
			}
			else if(s[j]!=st[i][j]){
				if(flag==1){
					flag=0;
					cout<<i;
				}
				cout<<" "<<j;
			}
		}
		if(flag==0){
			cout<<endl;
		}
	}
    return 0;
}
T4 立体炸弹
题目大意
题目给出每艘船的炸弹数量、装甲上限、作战时间、炸弹伤害和维修效率,要求计算所需维修装置的最小数量。
题解思路
本题本质为题目信息的理解与模拟,通过循环的方法模拟炸弹和维修装置的运行过程。由于规律难以获得并且数据范围较小,这里使用嵌套循环的方法,外层循环枚举维修装置的数量,内层循环模拟时间范围内的运行情况。
由于同秒内的维修生效在炸弹之后,所以需要先计算炸弹效果,未被炸毁时再计算维修效果,维修时注意装甲不能超出原有的装甲上限。
当超出时间后,仍在运行中的炸弹和维修装置仍会继续完成当前轮次的运行,这里在模拟时需要多模拟一轮并注意后续不再开启。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n,m,t;
    cin>>n>>m>>t;
    int x,y;
    cin>>x>>y;
    int flaga=0,flagb=0;
    int num=0;
    int minn=0;
    if(n*4*x>=m){
        minn=-1;
        cout<<minn<<endl;
        return 0;
	}
 
    for(int i=0;i<=n*4*x;i++){
        flaga=0;
        flagb=0;
        num=m;
        int flag=1;
        for(int j=0;j<=t+12;j++){
            if(j%12==0){
                if(flaga==1){
                    num=num-n*4*x;
                    flaga=0;
                }
                if(num<=0){
                    flag=0;
                    break;
                }
                if(j<=t){
                    flaga=1;
                }
            }
 
            if(j%10==0){
                if(flagb==1){
                    num=num+i*y;
                    if(num>=m){
                        num=m;
                    }
                }
                if(j<=t){
                    flagb=1;
                }
            }
        }
        if(flag==1){
            minn=i;
            break;
        }
    }
    cout<<minn<<endl;
    return 0;
}
T5 三好学生
题目大意
题目给出积分记录,根据记录累积每位同学的总积分,最后再按积分比例计算总积分。
题解思路
本题本质为结构体排序,每位同学存在多个分数和多条记录,并且总积分需要进行排序,所以采用结构体进行存储与排序。
需要注意的是,题目并没有说明编号是从 ,所以需要对整个可能的编号范围 进行遍历统计并标记有记录的同学编号,在排序时将是否有记录作为第一关键字进行排序。
另外对于总积分的输出格式,从样例中可以发现是输出实际的有效位,如果结果是整数就输出整数,如果结果存在小数部分则按小数实际大小输出。这里只存在一位小数和整数的两种情况,样例中都有包括。
参考代码
#include <bits/stdc++.h>
using namespace std;
struct student{
	int flag=0;
	int id;
	int a=0,b=0,c=0;
	double sum=0;
}st[2010];
 
bool cmp(student x,student y){
	if(x.flag==0||y.flag==0){
		return x.flag>y.flag;
	}
	else{
		if(x.sum==y.sum){
			return x.id<y.id;
		}
		else{
			return x.sum>y.sum;
		}
	}
}
int main() {
    int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y,a,b,c;
		cin>>x>>y>>a>>b>>c;
		if(st[y].flag==0){
			st[y].flag=1;
		}
		st[y].id=y;
		st[y].a=st[y].a+a;
		st[y].b=st[y].b+b;
		st[y].c=st[y].c+c;
	}
	for(int i=1;i<=2000;i++){
		if(st[i].flag==1){
			st[i].sum=1.0*(st[i].a*4+st[i].b*4+st[i].c*2)/10;//总积分可能存在小数部分
		}
	}
	sort(st****t+2000+1,cmp);
	for(int i=1;i<=2000;i++){
		if(st[i].flag==1){
			cout<<st[i].id<<" "<<st[i].sum<<endl;
		}
	}
    return 0;
}
T6 产量预测
题目大意
题目给出了从 开始加工到 的转化情况,要求从零开始计算一段时间后的各级产品数量。
题解思路
本题本质为对题目信息的模拟,按照时间顺序模拟各级工厂的运行情况。这里工厂的开工时间比较统一,所以可以优化为对每 分钟的时间节点进行模拟操作,不需要按每分钟进行模拟。
工厂的消耗与产出过程非常相似,所以可以将每级工厂的运行都总结为函数进行,在每个时间点按低级到高级的顺序依次模拟运行。由于同级工厂会统一开工,所以要注意标记当前是否有工厂在运行并记录运行工厂的数量。每轮运行时要注意先产出上一轮的产品,将记录的运行工厂数清空后,然后再考虑新一轮的运行情况。最后的一个整点同样要注意计算产出并消耗材料启动新一轮流程。
极限情况下可能存在  产品数量超出 int 范围的情况,所以要注意使用 long long 类型变量。
参考代码
#include <bits/stdc++.h>
using namespace std;
int t;
long long a,b,c,d,e,f,g,h,p;
long long n0,n1,n2,n3,n4;
int num[5];
int flag[5];
long long ans[5];
 
void fun0(){
	if(flag[0]==1){
		ans[0]=ans[0]+num[0]*a;
    	flag[0]=0;
	}
	flag[0]=1;
	num[0]=n0;
}
 
void fun1(){
	if(flag[1]==1){
		ans[1]=ans[1]+num[1]*c;
    	flag[1]=0;
	}
	if(ans[0]>=b){
		flag[1]=1;
		num[1]=min(n1,ans[0]/b);
		ans[0]=ans[0]-num[1]*b;
	}
}
 
void fun2(){
	if(flag[2]==1){
		ans[2]=ans[2]+num[2]*e;
    	flag[2]=0;
	}
	if(ans[1]>=d){
		flag[2]=1;
		num[2]=min(n2,ans[1]/d);
		ans[1]=ans[1]-num[2]*d;
	}
}
 
void fun3(){
	if(flag[3]==1){
		ans[3]=ans[3]+num[3]*g;
    	flag[3]=0;
	}
	if(ans[2]>=f){
		flag[3]=1;
		num[3]=min(n3,ans[2]/f);
		ans[2]=ans[2]-num[3]*f;
	}
}
 
void fun4(){
	if(flag[4]==1){
		ans[4]=ans[4]+num[4]*p;
    	flag[4]=0;
	}
	if(ans[3]>=h){
		flag[4]=1;
		num[4]=min(n4,ans[3]/h);
		ans[3]=ans[3]-num[4]*h;
	}
}
 
 
int main() {
	cin>>t;
	cin>>a>>b>>c>>d>>e>>f>>g>>h>>p;
	cin>>n0>>n1>>n2>>n3>>n4;
	
	for(int i=1;i<=t;i++){
		//0
		fun0();
		fun1();
		fun2();
		fun3();
		fun4();
 
		//15
		fun0();
 
		//30
		fun0();
		fun1();
 
		//45
		fun0();
	}
	fun0();
	fun1();
	fun2();
	fun3();
	fun4();
 
	for(int i=0;i<=4;i++){
		if(i!=0){
			cout<<" ";
		}
		cout<<ans[i];
	}
	cout<<endl;
    return 0;
}
这里因为工厂运行的模式非常相似,所以代码可以考虑复制粘贴后再修改,也可以在函数内部使用循环进行不同级工厂的运行。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int in[5], out[5];
int num[5]; //工厂数量
int w[5]; //上一次开工数量
int ans[5];
void f(int x) { //x级工厂  获取上一次的结果  并且再次开工
    //采集
    ans[x] += w[x] * out[x];
    if(x == 0) w[x] = num[x];
    else {
        w[x] = min(num[x], ans[x - 1] / in[x]);
        ans[x - 1] -= w[x] * in[x];
    }
}
int main() {
    int t;
    cin >> t;
    for(int i = 0; i < 5; i++) {
        if(i) cin >> in[i];
        cin >> out[i];
    }
    for(int i = 0; i< 5; i++) cin >> num[i];
    for(int i = 1; i <= t + 1; i++) {
        for(int j = 0; j < 5; j++) f(j);
        if(i <= t) {
            f(0);
            f(0); f(1);
            f(0);
        }
    }
    for(int i = 0; i < 5; i++) cout << ans[i] << ' ';
    return 0;
}
全部评论 2
- 被T6吓哭了 - 1周前 来自 广东 0- 对新人友好的小模拟 - 1周前 来自 广东 0
 
- qp - 1周前 来自 浙江 0




















有帮助,赞一个