国庆普及模拟赛-1 赛后总结

题目链接:

file:///D:/C++/%E9%9B%86%E8%AE%AD%E6%B5%8B%E8%AF%95/1001/2022%20-%20J2.pdf

 

T1:隔离

题意如图。需要求所有时间的最短。

思路:

不需要进行一次次枚举,先算出总共要办事的总时间sum,如果某一次时间超过240(需要隔离)就不回来了(反正也要隔离就一直干完了在回来)如果一直没有需要隔离,就进行分类

最后要判断来回所需要的时间和如果一直呆在B处隔离所花时间的大小

赛时代码

#include<bits/stdc++.h>
using namespace std;
int a[100050];
int main() {
	freopen("isolate.in","r",stdin);
	freopen("isolate.out","w",stdout);
	int n,ans=400,now=0;
	cin>>n;
	for(int i=1; i<=n; i++)cin>>a[i];
	if(n==1) 
		if(a[1]>=240) ans+=10080+a[1];
		else 	ans+=a[1];
	else if(n==2) 
		if(a[1]>=240) 		ans+=10080+a[1];
		else   if(a[2]>=240) 	ans+=+10080+a[2];
		else if(a[1]+a[2]<240)ans+=a[1]+a[2];
		else ans+=a[1]+a[2]+400;
	else
		for(int i=1; i<=n; i++) {
			if(a[i]>=240){
				ans=ans+400+10080+a[i];	
			}else if(now+a[i]<240) {
				ans+=a[i];
				now+=a[i];
			} else {
				ans=ans+a[i]+400;
				now=a[i];
			}
		}
	cout<<ans;
	return 0;
}//思路很混乱,看不懂了

(最后六十分

正确代码

#include<bits/stdc++.h>
using namespace std;
int a[100050],n,sum,now,flag,cnt;
int main() {
	freopen("isolate.in","r",stdin);//
	freopen("isolate.out","w",stdout);
	cin>>n;
    cnt=1;
	for(int i=1; i<=n; i++){
		cin>>a[i];//输入每次所需的时间
		if(a[i]>=240)flag=1;//如果有大于240(需要隔离的,就用flag标记一下
		sum+=a[i];//统计所有办事时间和
	}
	if(flag==1){//如果有>240的
		cout<<sum+10480;//直接一直呆在B,输出
		return 0;//就不需要后面的判断了
	}
	for(int i=1;i<=n;i++)//进行模拟n次办事
		if(now+a[i]>=240){//判断可不可以进行分组(一次干多件事),如果目前超过了
			cnt++;//组数++
			now=a[i];//之前的分组清空,新起一组
		}else		now+=a[i];//继续当前分组
	cout<<min(cnt*400,10480)+sum;//判断是来回跑还是一直呆在B时间大
	return 0;
}

 

T2和积

题目想法:

看到这道题,第一想法就是从M到N进行模拟(只能这样)因为是多测,所以在时间复杂度里还要乘上一个测试数据T。每次计算一个数的位数和和位数积需要复杂度一个常数10

所以时间复杂度为O(10NT)

这里面N和T都是不能优化的,只有常数可以优化。这里考虑使用记忆化,预处理每个数的位数和和位数积。优化后时间复杂度就是O(NT)

本题为多测!!!输出要换行!!!

PAC(赛时代码微改)

#include<bits/stdc++.h>//70分!为预处理!!!
using namespace std;
int S(int k) {
	int sum=0;
	while(k) {
		sum+=k%10;
		k/=10;
	}
	return sum;
}
int J(int R) {
	int ans=1;
	while(R) {
		ans*=R%10;
		R/=10;
	}
	return ans;
}
int  main() {
	freopen("sump.in","r",stdin);
	freopen("sump.out","w",stdout);
	int N,m,n,k,ans,cnt,mn;
	cin>>N;
	while(N--){
		cin>>m>>n>>k;
		ans=0,cnt=1,mn=-1;
		for(int i=m; i<=n; i++)
			if(S(i)==k&&J(i)> mn) {
				mn=J(i);
				ans=i;
			}
		cout<<ans<<" "<<mn<<endl;
	}
	return 0;
}

AC(稍微加了预处理) 

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
int a[N],b[N],T,m,n,k,ans,cnt,mn;
int S(int k) {
	int sum=0;
	while(k)	sum+=k%10,k/=10;
	return sum;
}
int J(int R) {
	int ans=1;
	while(R) 	ans=ans*(R%10),R/=10;
	return ans;
}
void solve() {
	cin>>m>>n>>k;
	ans=0,cnt=1,mn=-1;
	for(int i=m; i<=n; i++)//重复枚举每个n到m
		if(a[i]==k&&b[i]> mn) {//如果满足条件切乘积和max,就替换
			mn=b[i];
			ans=i;//记录满足条件的i
		}
	cout<<ans<<" "<<mn<<endl;
	return ;
}
int  main() {

	freopen("sump.in","r",stdin);
	freopen("sump.out","w",stdout);

	cin>>T;

	for(int i=1; i<=5e6; i++) {//预处理每个数的乘积和位数和
		a[i]=S(i);
		b[i]=J(i);
	}
	while(T--) {//进行多组数据
		solve();
	}
	return 0;
}

 

T3 电梯停靠

 思路:

像解一个绝对值方程,使用零点分段法。

例:        |x-5|+|x-7|

算当x<5、5<x<7,7<x(部分包含等于)

所以x点到各个上下车地点最小值就是最大最小点的中间值。(不然绝对会TLE 

赛时代码:

纯模拟,(要么wa,要么tle)最后20分

#include<bits/stdc++.h>

using namespace std;

const int N=5*1e5+5;
int a[5][N];

int main() {
	freopen("lift.in","r",stdin);
	freopen("lift.out","w",stdout);
	int n,m,bianhao=0,juli=N,ans;
	cin>>n>>m;
	for(int i=1; i<=m; i++) {
		cin>>a[1][i]>>a[2][i];
	}
	for(int x=1; x<=n; x++,ans=0) {
		for(int i=1; i<=m; i++) {
			ans=ans+abs(x-a[1][i])+abs(a[1][i]-a[2][i])+abs(a[2][i]-x);
		}
		if(ans<juli) {
			bianhao=x;
			juli=ans;
		}
	}
	cout<<bianhao<<" "<<juli;
	return 0;
}

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
int n,m,a[N],A[N],b[N],B[N];
int _abs(int x){
	return x>0?x:-x;
}

signed main() {
	freopen("lift.in","r",stdin);
	freopen("lift.out","w",stdout);
	cin>>n>>m;
	int sum=0;
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%lld %lld",&x,&y);
		sum+=_abs(x-y)*2;
		a[x-1]+=2,b[y+1]+=2;
	}
	for(int i=n;i>=1;i--){
		a[i]+=a[i+1];
		A[i]=A[i+1]+a[i];
	}
	int minn=1e18,idx;
	for(int i=1;i<=n;i++){
		b[i]+=b[i-1];
		B[i]=B[i-1]+b[i];
		int res=A[i]+B[i];
		if(res<minn) minn=res,idx=i;
	}
	cout<<idx<<" "<<minn+sum;
	return 0;
}

T4 分组选数

不会改!

总结:

本次模拟需要重视的细节很多,但大多数我没注意到。

在今后的比赛(模拟)中,要注意:

1,能多拿分就多拿分(争取前两题暴力模拟多得分,优化不重要(可能会错))后面的第四题,能A少数测试点,争取拿1~20分。

2,前面的题争取在前面时间内改完,不要遗留到后面

3,先读懂题在开始写,不要慌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值