模拟赛一补题报告
S12654马德栯
一.做题情况
第一题.00/100(赛后通过)
第二题.30/100(赛后通过)
第三题.10/100(赛后通过)
第四题.30/100(赛后通过)
二.题解报告
T1:
(cook.cpp/c)
做饭
问题描述
小可对达达真的是真爱!
小可为了体现对达达的爱,特意要为即将下班的达达做一顿丰富的晚饭!已知达达到家时间是K时刻,并且知道当前处在now时刻。
小可需要p秒时间去准备好饭菜。
假设小可制作晚饭总共需要q秒时间。
请问赶在达达到家之前,小可是否能准备完晚饭。
输入格式
输入第一行按照
hh:mm:ss,即 时:分:秒 表示的时间now,表示当前时间。
输入第二行按照
hh:mm:ss,即 时:分:秒 表示的时间K,表示达达到家的时刻。
输入第三行两个整数p,q分别表示准备时间和制作时间。
输出格式
如果可以赶在达达回家之前制作完晚饭,输出 Yes ,否则输出 No 。
输入样例1
11:45:14
19:19:0
114 514
输出样例1
Yes
输入样例2
11:45:14
11:56:0
1145 14
输出样例2
No
提示
输入的 和 使用距离某个时刻之后的时分秒记录,可能不符合现实中的时间记录。时间是24小时进制,时间的计算方式与现实生活中相同。
数据描述
使用
分别表示输入时刻中的时、分、秒。
对于40%的数据:
0<=hh<=23,0<=min,ss<=59,0<=p,q<=1000
对于100%的数据:
0<=hh,min,ss<=10^6,0<=p,q<=10^8
样例解释1:
114+514=628秒,小可做饭一共花628 秒,11:45:14~19:19:0一共27226 秒, 628<27226秒,所以输出Yes(后两个字符一定要小写)。
样例解释2:
1145+14=1159秒,11:45:14~11:56:0是646秒,1159>646所以输出No。
错因:
Yes中"es"大写,No中"o"大写,小时与分钟的进率写成24。
分析:
这道题可以把时间换算成秒,再和小可做饭的总时间比较。
因为时间最小都是10的6次方,所以要用long long 类型。
也可以满六十进一:60秒->一分,60分->1小时,24小时->一天。这种方法要考虑隔天问题,时间细节比较多,可以用来拿步骤分。
程序:
#include<cstdio>
using namespace std;
int main(){
long long shi_jian,sh1,fe1,mi1,sh2,fe2,mi2,p,q;
scanf("%lld:%lld:%lld",&sh1,&fe1,&mi1);
scanf("%lld:%lld:%lld",&sh2,&fe2,&mi2);
shi_jian = (sh2 * 3600 + fe2 * 60 + mi2) - (sh1 * 3600 + fe1 * 60 + mi1);
printf("%lld",shi_jian);
return 0;
}
T2:
(criterion.cpp/c)
评价标准
问题描述
给定一个长度为 的数组 ,其中包含S1,S2.....Sn。
定义数组 的评价标准为: 最大值-最小值 。
小可同学觉得问题过于简单。然后定义了一种操作:给定一个操作值 ,然后任意从数组中选择一个数字 ,可以将数字 加上 ,或者减去 ,之后得到一个新的数组,并使得新数组的评价标准最小。最终输出最小的评价标准。
输入格式
输入第一行包含两个整数 。
第二行输入数组 ,总共 个整数,使用空格分开。
输出格式:输出一行,包含一个整数,表示操作后最小的评价标准。
输出一行,包含一个整数,表示操作后最小的评价标准。
输入样例 5 114
19 19 810 114 514
输出样例 677
数据描述
对于40%的数据:2<=n<=100,0<=Si,k<=1000
对于100%的数据:2<=n<=10^6,0<=|Si|,|k|<=10^8
5 114
19 19 810 114 514
677
样例分解释:
把810减去k(114),为696,再减19,为677。
错因:
考虑到太少,只考虑了最大值减k的情况。
分析:
这个题可以改变最大值和最小值,改变最大值有三种情况:1.它还是最大值,2.它变成了次大值,3.它变成了最小值。改变最小值也有三种情况:1.它还是最小值,2.它变成了次小值,3.它变成了最大值。(加最大值和减最小值毫无意义!)暴力的话,可以把所以情况用if列出来:
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const ll N=1E6+10,M=0x3F3F3F3F;
ll n,k,maxx=-M,minn=M,cmin=M,cmax=-M,s[N],ans;
int main(){
cin>>n>>k;
k=abs(k);
for (int i=1;i<=n;i++){
cin>>s[i];
maxx=max(maxx,s[i]);
minn=min(minn,s[i]);
}
ans=maxx-minn;
int c1=0,c2=0;
for (int i=1;i<=n;i++){
if (s[i]==minn) c1++;
if (s[i]==maxx) c2++;
if (s[i]!=minn && s[i]>cmin) cmin=s[i];
if (s[i]!=maxx && s[i]<cmax) cmax=s[i];
}
if (c1>1 && c2>1){
cout<<ans;
return 0;
}
if (c1==1 && c2>1){
ll t=k+minn;
if (t>=cmin && t<maxx) ans=min(ans,maxx-cmin);
else if (t<cmin){
minn+=k;
ans=min(ans,maxx-minn);
}
else if (t>=maxx){
maxx=t;
ans=min(ans,maxx-cmin);
}
}
else if (c1>1 && c2==1){
ll t=maxx-k;
if (t<=cmax && t>minn) ans=min(ans,cmax-minn);
else if (t>cmax){
maxx=t;
ans=min(ans,maxx-minn);
}
else if (t<=minn){
minn=t;
ans=min(ans,cmax-minn);
}
}
else{
if (k+minn>=cmin && k+minn<maxx) ans=min(ans,maxx-cmin);
if (maxx-k<cmin){
minn+=k;
ans=min(ans,maxx-minn);
}
if (k+minn>=maxx){
maxx=k+minn;
ans=min(ans,maxx-cmin);
}
if (maxx-k<=cmax && maxx-k>minn) ans=min(ans,cmax-minn);
if (maxx-k>cmax){
maxx-=k;
ans=min(ans,maxx-minn);
}
if (maxx-k<=minn){
minn=maxx-k;
ans=min(ans,cmax-minn);
}
}
cout<<maxx-minn;
return 0;
}
我们也可以优化一下:
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const ll N=1E6+10,M=0x3F3F3F3F;
ll n,k,s[N],a[N],b[N],sum1,sum2;
int main(){
cin>>n>>k;
k=abs(k);
for (int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(a+1,a+n+1);
sort(b+1,b+n+1);
a[1]+=k;
b[n]-=k;
sort(a+1,a+n+1);
sort(b+1,b+n+1);
sum1=a[n]-a[1];
sum2=b[n]-b[1];
cout<<min(sum1,sum2);
return 0;
}
T3:
(buy.cpp/c)
小可买菜
问题描述
小可对达达真的是真爱!
小可为了体现对达达的爱,特意要为即将下班的达达做一顿丰富的晚饭!做饭之前需要先购买足够的新鲜的食材,小可来到了超市。
小可列了一个购买清单,总共有n个食材需要购买,在超市中第i个食材的价格是Ui。
今天超市正在进行促销活动,每满两个商品,都可以进行促销活动,使用两个商品中最高价格购买当前这两件商品。
为了节省金钱,小可还在线购买了k张超市折扣券,每两件商品可以使用一张折扣券,使用两个商品中最低价格购买当前这两件商品。
注意:商品不能重复参加活动。
请问小可购买清单中所有物品都购买后,最低花费多少元。
输入格式
第一行输入两个整数n,k含义如题所示。
第二行输入n个整数Ui,数字以空格分隔,表示每个食材价格。
输出格式
输出一行包含一个整数,表示小可购买清单中所有物品都购买后,最低花费多少元。
输入样例1
4 1
1 2 3 4
输出样例1
4
输入样例2
13 2
20
数据描述
对于40%的数据:1<=n<=100,0<=k<=1,0<=Ui<=100
对于100%的数据:1<=n<=10^8,0<=k<=10^5,0<=Ui<=10^6
样例分解释1:
1和4一起用优惠券,花1元,2和3一起买,花3元,1+3=4元。
样例分解释2:
1和9一起用优惠券,花1元,2和8一起用优惠券,花2元,3和3一起买,花3元,6和4一起买,花6元,7和8一起买,花8元,1+2+3+6+8=20元)
错因:
太罗嗦,以至于后面自己都晕了(而且测的样例太少了)。freopen忘记解除注释了。
分析:
这个题可以用双指针的方法,有有优惠券时让当前最大的和最小的一起买,所以要先排序(栓指针的前提之一就是有序),没有优惠券后,让相邻的两个数一起买。
程序:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N=1E6+10;
ll n,k,a[N],sum;
int main(){
scanf("%lld %lld",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
ll l=1,r=n;
while(k--&&l<=r){
sum+=a[l];
l++;
r--;
}
while(l<=r){
sum+=a[r];
r-=2;
}
printf("%lld",sum);
return 0;
}
T4:
(cuisine.cpp/c)
美味佳肴
问题描述
吃面包要配果酱
吃薯条要配番茄酱
。。。
达达发现,小可准备的这些美食中,很多食物搭配起来吃最美味了!
小可为了让达达吃起来最顺利,已经给食物提前进行了标记,标记分为两种: 大写字母 和 ? ,相同大写字母表示两个食物搭配起来吃最美味, ? 则表示搭配任何一个食物吃都非常美味,但是达达有习惯,一旦使用当前这种食物搭配另一个食物,达达就不会再去搭配其他食物吃,也就是说每个 ? 确定与某个食物搭配后,则不能再与其他食物搭配食用。
现在请问小可制作的饭菜中最多有多少种不同的搭配。注意:
不同的搭配表示,字符相等,但是位置不同。
形式化的讲,给定一个由 大写字母 和 ? 构成的字符串 ,在字符串中存在l,r满足l<r且s[l]==s[r],则表示一种美味搭配。找出最多的不同的搭配,当l不同或r不同,就表示一种不同搭配。
输入格式
多组测试,第一行一个整数T,表示测试组数。
然后对于每组测试数据,输入一个字符串s,含义如题所示。
输出格式
对于每组测试数据,输出一个整数,表示不同的搭配数量。
输入样例
4
?A?
ABCDBDABCDBA
ABCD?ACNBADADA
ERTETHD?ERY?ERHDFS?
输出样例
3
13
20
27
数据描述
假设L表示字符串s的长度。
对于30%的数据,所有的s中都不包含 ? ,1<=L<=10^3
对于100%的数据,1<=T<=10,1<=L<=10^6
样例分解释:
?和A组合为:?A,??,A?
ABCDBDABCDBA组合为:AA,AA,BB,BB,......
ABCD?ACNBADADA组合为:A?,AA,AA,AA,AA,BB,BB,.....
.........
错因:
对“?”的处理不明确,"?"只能用一次。
分析:
"?"只能用一次,所以我们要把它变成出现次数最多的字符。
程序:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
long long a[100],t;
string s;
int main(){
cin>>t;
while(t--){
memset(a,0,sizeof(a));
cin>>s;
int maxx=0;
int len=s.size(),temp=0;
long long ans=0;
for (int i=0;i<len;i++){
a[s[i]]++;
if (s[i]!='?')
if (a[s[i]]>maxx){
maxx=a[s[i]];
temp=s[i];
}
}
if (a['?']==0)
for (int j=65;j<=90;j++)
ans+=a[j]*(a[j]-1)/2;
else{
a[temp]+=a['?'];
for (int j=65;j<=90;j++)
ans+=a[j]*(a[j]-1)/2;
}
cout<<ans<<"\n";
}
return 0;
}