总报告
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,⋯⋯,Sn。
定义数组 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 个食材的价格是 Vi。
今天超市正在进行促销活动,每满两个商品,都可以进行促销活动,使用两个商品中最高价格购买当前这两件商品。
为了节省金钱,小可还在线购买了 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;
}
警钟长鸣
暴力无涯,公式是岸。
枚举超时,优化万岁。
数据范围,关键者哉。
运行速度,重要者也。
时间超限,代码重写。
警钟长鸣,以示后人。
总结
先想清楚题目,再想想方法,不然就会逝。