C++补题报告

                                                     模拟赛一补题报告
                                                        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;
} 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值