模拟三补题报告

S15192

一、题目报告

         考试中第一、二题AC,第三题30分(6组数据),第四题0分;比赛后全部AK。

二、赛中概况 

        第一题看完题后觉得很简单,写了一下,成功AC。

        第二题看完题后觉得很简单,写了一下,样例没过,改了几遍,成功AC。

        第三题看后有思路,但数据太大,有14个样例超时,只得30分。

        第四题完全没思路,得了零分。

三、解题报告

T1.十五的月亮(moon)

题目情况 

        比赛时AC

题目描述

        假设一个每个月都是30天,用 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 表示一个月30天中的月亮的大小。

        给出n天的月亮大小,请预测接下来一天的月亮的大小情况;变大的话输出UP,变小的话输出DOWN,如果无法预测请输出-1。

题目解析

        分类讨论即可:
                如果最后一天是0,则一定是UP
                如果最后一天是 15,则一定是DOWN

        否则:
                如果只有一天,则是-1
                如果n>1的花,直接进行判断即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m[108];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>m[i];
	}
	if(n==1&&m[n]!=0&&m[n]!=15){
		cout<<-1<<"\n";
	}
	else if(m[n]==0) cout<<"UP\n";
	else if(m[n]==15) cout<<"DOWN\n";
	else if(m[n]<m[n-1]) cout<<"DOWN\n";
	else if(m[n]>m[n-1]) cout<<"UP\n";
	return 0;
}

T2.原码反码补码(binary)

题目情况 

        比赛时AC

题目描述

        小可今天学习了原码反码补码的相关内容,想让你帮他写一个程序:

        对于给定的二进制字符串原码,输出其对应的反码和补码。

        原码转换成反码的规则:

        原码的第一位为符号位,若符号位为 0,则反码与原码相同。若符号位为 1,则符号位不变,将其他位全部取反。

        反码转换成补码的规则:

        如果反码的符号位是0,则补码与反码相同,否则,补码等于反码+1 。

题目解析

        模拟即可。
        如果最高位是0,则直接输出两次s即可。
        如果最高位是1,先除了最高位都0变1,1变0,然后输出。之后,再考虑+1。
此时需要考虑符号位也有可能会+1,而溢出。

AC代码

#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
	cin>>s;
	int len=s.size();
	if(s[0]=='0'){
		cout<<s<<"\n"<<s;
		return 0;
	} 
	for(int i=1;i<len;i++){
		if(s[i]=='0') s[i]='1';
		else s[i]='0';
	}
	cout<<s<<"\n";
	for(int i=len-1;i>=0;i--){
		if(s[i]=='0'){
			s[i]='1';
			break;
		}
		s[i]='0';
	}
	cout<<s<<"\n";
	return 0;
}

T3.区间数位和(section)

题目情况 

        比赛时30分

题目描述

        对于给定的数字n,求1到n所有的数字,其十进制位的所有位的和是多少。

例如 n=12,则其答案为1+2+3+4+5+6+7+8+9+(1+0)+(1+1)+(1+2)=51

题目解析

        每次查询都是 1到x 所有的数字的数位和。

        所以可以考虑前缀和处理。
        预处理一个sum数字,sum[i] 表示1到i所有数字的数位和。所以我们可以先求sum[1]到sum[10^6]。
然后对于每组查询, 输出即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int m=1e6;
int a[m+8];
int main(){
	for(int i=1;i<=m;i++){
		int t=i,sum=0;
		while(t){
			sum+=t%10;
			t/=10;
		}
		a[i]=a[i-1]+sum;
	}
	int t;
	cin>>t;
	while(t--){
		int n;
		scanf("%d",&n);
		printf("%d\n",a[n]);
	}
	return 0;
}

T4.双人博弈(game)

题目情况 

        比赛时0分

题目描述

       小可和达达正在打牌,他们俩每人都有n张牌,每张牌的大小是从0到9的。

        每一轮他们俩每个人出一张牌,数字大的获胜。特殊的如果数字相同则为平局。

        但是阴险狡诈的达达,已经知道了小可的出牌顺序为S。所以他可以调整自己的牌的顺序来应对小可的牌。

        请问达达最少可以输多少次,最多可以赢多少次。

题目解析

        由于只有达达可以移动卡牌,所以我们围绕达达考虑。
        因为达达的顺序可以随意移动,所以小可的顺序其实不重要,所以我们先把小可和达达的牌从小到大排序。
        用a[i]代表小可的当前的数字的大小。
        b[j] 代表达达的当前的数字的大小。

        对于第一个问题:达达最少可以输多少次。
        也就是说,小可不赢就行,也就是需要 a[i] <= b[j] 即可。所以对于排序好的序列,考虑双指针。
        如果满足条件,那么i++,j++。
        如果当前的a[i]比b[j]大,那么当前的b[j] 一定会输,所以我们考虑j++,找一个可以赢a[i] 的值即可。

对于第二个问题:达达最多可以赢多少次。和上面问题同理,只不过需要考虑 a[i]<b[j] 。

AC代码

#include<bits/stdc++.h>
using namespace std;
char a[100008],b[100008];
int main(){
	int n,ans1=0,ans2=0;
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n;i++) cin>>b[i];
	sort(a,a+n);
	sort(b,b+n);
	int i=0,j=0;
	while(i<n&&j<n){
		if(b[j]>=a[i]) i++,j++;
		else j++,ans1++;
	}
	i=j=0;
	while(i<n&&j<n){
		if(b[j]>a[i]) i++,j++,ans2++;
		else j++;
	}
	cout<<ans1<<"\n"<<ans2<<"\n"; 
	return 0;
}

2024/10/6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值