可达鸭CSP-X模拟1补题报告

总报告

2024.10.2尹一珩补题报告

198分,很失望,第一题应该AC的,下次要更细心

题目得分

18,80,70,30

题目1:做饭(cook)

题目内容

时空限制

1s,256M,比较充裕

问题描述(简化版)

已知达达到家时间是 K 时刻,并且知道当前处在 now 时刻。

小可需要 p 秒时间去准备好饭菜。

假设小可制作晚饭总共需要 q 秒时间。

请问赶在达达到家之前,小可是否能准备完晚饭。

(求a时b分c秒减去d时e分f秒,与(g+h)秒作比较)

做题过程&结果

AC代码&AC思路

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<string.h>
#include<iomanip>
using namespace std;
struct t{
	long long hor,min,sec;
}k,now;
long long p,q,j,l1,l2;
string a,b;
int main(){
    scanf("%lld:%lld:%lld",&now.hor,&now.min,&now.sec);
    scanf("%lld:%lld:%lld",&k.hor,&k.min,&k.sec);
    cin>>p>>q;
    l1=(now.hor*3600+now.min*60+now.sec);
	l2=(k.hor*3600+k.min*60+k.sec);
    if((l2-l1)>(p+q)) cout<<"Yes";
    else cout<<"No";
    return 0;
}

 先用scanf(scanf可以提取被符号包围的数),接下来无需60进制高精度,只需统一到秒进行运算,随后判断(这里有个啸坑,做完时刚好到时间也不行)

错误原因(死因) 

这道题非常简单,但是粗心了(眼瞎,脑残),痛失82分

1.减数与被减数搞混了(数学老师:6)

2.审题不清,在最后的判断加了个等号,痛失一个点

总结

这道题应该AC的,结果因为一些小错,最后只得了18分(两个点)

题目2:评价标准(criterion)

题目内容

时空限制

1s,256M,充裕

问题描述(简化版)

给定一个长度为 n 的数组 S ,其中包含S1,S2,⋯⋯,S​n​​

定义数组 S 的评价标准为:最大值-最小值

小可同学觉得问题过于简单。然后定义了一种操作:给定一个操作值 k,然后任意从数组中选择一个数字x,可以将数字 x 加上 k,或者减去 k,之后得到一个新的数组,并使得新数组的评价标准最小。最终输出最小的评价标准。

(使数组任意元素+k(-k)后数组内最大值-最小值的差最小化)

做题过程&结果 

AC代码&AC思路

 我的AC代码

//代码是AC的,但是可达鸭编译器不支持我一开始在定义minn时使用的INT_MAX
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<string.h>
#include<iomanip>
using namespace std;
long long n,k,maxx=-1,minn=0x3f3f3f3f,l[10000005],t[10000005],m1,m2;
bool cmp(long long a,long long b){
	return a>b;
}
int main(){
    cin>>n>>k;
    for(long long i=1;i<=n;i++){
    	cin>>l[i];
    	if(l[i]>maxx) maxx=l[i];
    	if(l[i]<minn) minn=l[i];
    	t[i]=l[i];
	}
	if(n==1){
	    cout<<0;
	    return 0;
	}
    k=abs(k);
	sort(t+1,t+n+1,cmp);
	t[1]-=k;
	sort(t+1,t+n+1,cmp);
	m1=t[1]-t[n];
	for(int i=1;i<=n;i++) t[i]=l[i];
	sort(t+1,t+n+1,cmp);
	t[n]+=k;
	sort(t+1,t+n+1,cmp);
	m2=t[1]-t[n];
	cout<<min(m1,m2);
    return 0;
}

 思路就是要么最大值-k,要么最小值+k,之后sort排序一下,再求最小值就可以了。很可惜,虽然一个O(N)+四个sort,卡时间过,但是被可达鸭的BUG卡了,结果CE,0分,把INT_MAX改成0x3f3f3f3f就对了,DEV上完全没问题。(原本可得80分)

再贴个老师的AC代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<string.h>
#include<iomanip>
using namespace std;
const int inf=0x3f3f3f3f;
long long max1,max2,a1,a2,min1,min2,n1,n2,nmax,nmin,ans=0x3f3f3f3f,n,k,l[10000005];
bool cmp(long long a,long long b){
	return a>b;
}
int main(){
    cin>>n>>k;
    k=abs(k);
    max1=-inf,max2=-inf,min1=inf,min2=inf;
    for(long long i=1;i<=n;i++){
    	cin>>l[i];
    	if(l[i]>max2){
    	    if(l[i]>max1){
    	        a2=a1,max2=max1;
    	        a1=i,max1=l[i];
    	    }else{
    	        a2=i,max2=l[i];
    	    }
    	}
    	if(l[i]<min2){
    	    if(l[i]<min1){
    	        n2=n1,min2=min1;
    	        n1=i,min1=l[i];
    	    }else{
    	        n2=i,min2=l[i];
    	    }
    	}
	}
	l[n1]+=k;
	nmin=min(min2,l[n1]);
	nmax=max(max1,l[n1]);
	ans=min(ans,nmax-nmin);
	l[a1]-=k;
	nmax=max(max2,l[a1]);
	nmin=min(min1,l[a1]);
	ans=min(ans,nmax-nmin);
	cout<<ans;
    return 0;
}

同时求最大,次大值,最小,次小值,时间复杂度O(N)很健康,不赘述了。

错误原因

可达鸭的BUG,真的很开心

其次还是细节:k的数据范围里是用的|k|(绝对值),脑残的我没加abs(),痛失20分

总结

这道题被坑了,0分,下次直接用0x3f3f3f3f

题目3:小可买菜(buy)

题目内容

时空限制

1s,256M,正常时空

问题描述(简化版)

小可列了一个购买清单,总共有 n 个食材需要购买,在超市中第 i 个食材的价格是 V​i​​

今天超市正在进行促销活动,每满两个商品,都可以进行促销活动,使用两个商品中最高价格购买当前这两件商品。

为了节省金钱,小可还在线购买了 k 张超市折扣券,每两件商品可以使用一张折扣券,使用两个商品中最低价格购买当前这两件商品。

注意:商品不能重复参加活动。

请问小可购买清单中所有物品都购买后,最低花费多少元。

(求所有商品最低价格(两种活动间选择))

做题过程&结果

AC代码&AC思路

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<string.h>
#include<iomanip>
using namespace std;
long long n,k,l[1000005],cnt,con;
bool cmp(long long a,long long b){
	return a>b;
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>l[i];
    sort(l+1,l+n+1,cmp);
	for(int i=1;i<=k&&i<=n/2;i++){
    	cnt+=min(l[i],l[n-i+1]);
    	l[n-i+1]=0;
    	l[i]=0;
	}
	sort(l+1,l+n+1,cmp);
	for(int i=1;i<=n;i++){
    	if(l[i]==0){
    		con=i;
    		break;
		}
	}
	//sort(l+1,l+con+1,cmp);
    for(int i=1;i<=n;i+=2){
    	cnt+=max(l[i],l[i+1]);
    	l[i+1]=0;
    	l[i]=0;
	}
	for(int i=1;i<=n;i++){
    	cnt+=l[i];
	}
	cout<<cnt;
    return 0;
}

思路就是判断优惠用法:

优惠券:读题可知是取两个里便宜的一个,是min(a,b),所以用最便宜的+最贵的

商场活动:和上一个差不多,但是改成取贵的了,max(a,b),所以最贵的+次贵的

老师做法是用while做双指针扫描,思路相同,代码没存不贴了。

错误原因

对了7个点,共9个点。

我犯了一个致命的错误,提交时忘记删提示语了,还好是模拟赛。

其次对于倒数第二个循环的特点判断失误,痛失20分

总结

得了70分,其实这个题应该0分的,以后得记得把提示语删干净点

题目4:美味佳肴(cuisine)

题目内容

时空限制

1s,256M

问题描述(简化版)

小可为了让达达吃起来最顺利,已经给食物提前进行了标记,标记分为两种:大写字母 和 "?",相同大写字母表示两个食物搭配起来吃最美味,“?”则表示搭配任何一个食物吃都非常美味,但是达达有习惯,一旦使用当前这种食物搭配另一个食物,达达就不会再去搭配其他食物吃,也就是说每个?确定与某个食物搭配后,则不能再与其他食物搭配食用。

现在请问小可制作的饭菜中最多有多少种不同的搭配。

注意:不同的搭配表示字符相等,但是位置不同

(求搭配方式,要注意的是,字符输入顺序不重要)

做题过程&结果

AC代码&AC思路

#include<bits/stdc++.h>
using namespace std;
int t,maxx,id;
long long a[300],ans;
string s;
int main(){
    cin>>t;
    while(t--){
        memset(a,0,sizeof(a));
        maxx=id=ans=0;
        cin>>s;
        for(int i=0;i<s.size();i++) a[s[i]]++;
        for(int i=0;i<300;i++) if(char(i)!='?'&&a[i]>maxx) maxx=a[i],id=i;
        a[id]+=a['?'];
        a['?']=0;
        for(int i=0;i<300;i++){
            if(a[i]!=0) ans+=a[i]*(a[i]-1)/2;
        }
        cout<<ans<<'\n';
    }
}

代码非常短。

只需要统计字符个数就可以了,但是“?”的处理需要好好想一想:

根据题目,假设输入字符A的个数为 n ,那么A的总搭配数为:

dps(A)=(n-1)+(n-2)+......+1

来个栗子,假设字符串是“ABCHHHASASASAA”,那么第一个A可以给所有后面的A配,第二个A可以给它后面的A配......最后一个A没办法和任何人配。

那么再假设有一个“?”字符,很明显,分配给A会使A的搭配数增加n,可以看出,n越大,也就是说A的出现次数越多,“?”的效用越大。所以分配给出现次数最多的字符即可。

错误原因

我的代码是可以暴力AC的,但时间复杂度过高,最后只对了三个点

TLE代码献上

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<string.h>
#include<iomanip>
using namespace std;
int t,i=1,ton[100],maxx,maxt;
long long cnt;
string s;
int main(){
    cin>>t;
    while(t--){
    	cin>>s;
    	cnt=0;
    	memset(ton,0,sizeof(ton));
    	maxt=0;
    	//cout<<"Case "<<i++<<":"<<'\n';
    	for(int i=0;i<s.size();i++){
    	    if(s[i]!='?') ton[s[i]]++;
    	}
    	for(int i=0;i<30;i++){
    	    if(ton[i]>maxx) maxx=ton[i],maxt=i;
    	}
    	for(int i=0;i<s.size();i++){
    	    if(s[i]=='?') s[i]=s[maxt];
    	}
    	for(int l=0;l<s.size()-1;l++){
    		bool flag=0;
    		for(int r=l+1;r<s.size();r++){
    			if(flag) continue;
    			if(s[l]==s[r]){
					cnt++;
				}
			}
		}
		cout<<cnt<<'\n';
	}
    return 0;
}

 实际上接下来贴的代码可以用公式

for(int l=0;l<s.size()-1;l++){
    bool flag=0;
    for(int r=l+1;r<s.size();r++){
    	if(flag) continue;
    	if(s[l]==s[r]){
			cnt++;
		}
	}
}

然后,套公式,就A了

for(int i=0;i<300;i++){
    if(a[i]!=0) ans+=a[i]*(a[i]-1)/2;
}

警钟长鸣 

暴力无涯,公式是岸。

枚举超时,优化万岁。

数据范围,关键者哉。

运行速度,重要者也。

时间超限,代码重写。

警钟长鸣,以示后人。

总结

先想清楚题目,再想想方法,不然就会逝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值