CSP-X复赛模拟一补题报告
时间:2023年10月1日
S12004 张伯钧
一、分数:
总分:0’
T1【爬楼梯】:0’
T2【字符折线图】:0’
T3【吉利数】:0’
T4【路灯照明】:0’
二、比赛过程:
都直接把测试样例输出了
第一题:
//题目没有读懂,思路更有问题。
1.这一楼究竟是两层还是一层。2.小可和达达上了一层楼后要是还有步数不能要。
第二题:
//思路没有问题,程序全是问题。
1.数组下标变量向上是--不是++。2.先是行再是列,行是横着的,列是竖着的。
第三题:
//思路似乎对了,程序不停报错。
1.我也不知道错哪了。2.忘去注释了。
第四题:
//题目基本没读,直接输出样例。
1.时间不够。2.也看不懂。
三、比赛分析:
第一题:
题目描述:
小可和达达不打算坐电梯,于是他们打算爬楼梯爬上来!小可和达达从第一层出发,小可记录了每一步迈出去的距离能够跨越多少个台阶,达达记录了迈多少个台阶能够到达下一个平台。和很多大楼类似,每次爬楼梯到达一个平台,就需要转身再爬,到达两个平台代表上了一层楼。
请你计算一下,现在小可和达达已经到达了多少层!例如小可到了第八层,然后又向上爬了若干台阶,但是没有到第九层,那么输出第八层。
输入描述:
第一行两个正整数n和x,代表小可迈了n步,x个台阶能够上一楼。
第二行n个整数,代表小可每一步迈出去的距离能够跨越多少个台阶。
输出描述:
如题,输出一个整数,代表现在小可和达达已经到达了多少层。
样例输入1
10 10
2 5 3 7 3 1 5 4 5 5
样例输出1
3
样例输入2
3 5
3 5 2
样例输出2
1
样例输入3
5 5
10 10 10 10 10
样例输出3
3
提示
题目中的楼梯和现实生活中常见的楼梯结构类似,小可记录的是每一步迈出去的距离能够跨越多少个台阶,比如还剩一个台阶就能到达下一个平台,小可步子迈的再大,也只能上一个台阶。不存在一步跨越好几个平台的情况。当然,小可肯定是尽可能多地迈步。比如小可一步能跨越55个台阶,并且还是到不了下一层,那么小可这一步就一定迈了55个台阶。
数据
思路:
把小可迈的台阶累加
如果上了一个平台,就让楼层计数器++,然后把多余的步数清零
比如小可的步数(n个整数)分别是2 5 5 7,而上一层平台的步数(x)是10,那么先把前两次迈的步数相加2+5=7,然后现在还差3,但下一个数是5,不是3,就让他先迈3步,到达了一个平台,那剩下那两步就不能要了,所以步数计数器清零。
代码实现:
#include<iomanip>
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int main(){
long long n,a[100005],x;//定义
cin>>n>>x;//输入
for(int i=1;i<=n;i++){
cin>>a[i];//输入
}
int c=0,sum=0;
for(int i=1;i<=n;i++){
c+=a[i];
if(c>=x){//判断到了一层
sum++;//计数器++
c=0;
}
}
cout<<sum/2+1;//输出
return 0;
}
第二题:
题目描述:
字符串也是有起伏的!我们根据一个字符串,可以画出一个折线图。从第二个字符开始,如果它比它的上一个字符大,那么就是上升的,画一个/;如果和上一个字符相同,那么画一个-;如果比比上一个字符小,那么就是下降的,画一个\。并且上升的时候,要向上一行,下降的时候向下一行。具体例子如下:
字符串hkrzyqqqmi:
/\
/ \
/ --
\
\
注意控制格式,空白处使用空格填充,不要输出多余的空格。
输入描述
一个字符串,长度不超过100100,只包含小写字母。
输出描述
如题,根据输入的字符串画出折线图。
样例输入1
zyxvu
样例输出1
\
\
\
\
样例输入2
abcde
样例输出2
/
/
/
/
样例输入3
hhhhh
样例输出3
----
样例输入4
babababa
样例输出4
\/\/\/\
样例输入5
hikgabzph
样例输出5
/\ /\
/ \/ \
样例输入6
abcccddddccc
样例输出6
---
/ \
-- --
/
/
提示
当前字符和上一个字符相等时,输出的是减号而不是下划线。
数据
设n代表字符串长度:
思路:
如果想要100%正确那么就要用数组来实现,首先定义一个二维数组(char类型)全部初始化为空格,再定义一个控制下标的变量,每判断一次就在相应的位置放上"/","-","\"之一最后输出的时候要把后面的空格去掉,每行从后遍历找到第一次出现字符的位置记录下来,再从头输出到这。
代码实现:
#include<iomanip>
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
char s[205][205];
void init(){
for(int i=0;i<=200;i++){
for(int j=0;j<=200;j++){
s[i][j]=' ';
}
}
}
int main(){
string a;
cin>>a;
init();//初始化数组
int len=a.size(),y=100,min=205,max=0;
for(int x=1;x<len;x++){//遍历数组
if(a[x-1]<a[x]){//递增
if(s[y][x-1]=='/'){
y--;
}
else if(s[y][x-1]=='-'){
y--;
}
s[y][x]='/';
}
else if(a[x-1]==a[x]){//相等
if(s[y][x-1]=='/'){
y--;
}
else if(s[y][x-1]=='\\'){
y++;
}
s[y][x]='-';
}
else if(a[x-1]>a[x]){//递减
if(s[y][x-1]=='\\'){
y++;
}
else if(s[y][x-1]=='-'){
y++;
}
s[y][x]='\\';
}
if(y<min){
min=y;
}
if(y>max){
max=y;
}
}
int c;
for(int i=min;i<=max;i++){
for(int j=len-1;j>=1;j--){
if(s[i][j]!=' '){
c=j;
break;
}
}
for(int j=1;j<=c;j++){
cout<<s[i][j];
}
cout<<endl;
}
return 0;
}
第三题:
题目描述:
小可认为一个数字中如果有44这个数字就是不吉利的。相对的,其他的数字就是吉利的。吉利的数字有1,2,3,5,6,7,8,9,10,..
小可想知道,第n个吉利的数字是多少。
输入描述
第一行一个正整数t,代表有t组输入。
接下来t行,每行一个正整数n,代表小可想知道第n个吉利的数字是多少。
输出描述
对于每组输入,输出一行,代表相应的答案。
样例输入
5
1
2
14
255
12345678999999
样例输出
1
2
16
313
58737318092550
数据范围
对于20%的数据,t=1,n≤10
对于40%的数据,t≤10,n≤100
对于60%的数据,t≤10,n≤10^6
对于80%的数据,t≤5×10^5,n≤10^6
对于100%的数据,t≤5×10^5,n≤10^18
思路:
非常复杂,先转九进制,因为十进制有10个数(0,1,2,3,4,5,6,7,8,9)现在要把4去掉就只剩9个数了(0,1,2,3,5,6,7,8,9)
九进制正好有九个数(0--8),现在看看下表(都是九进制,左边是不去4的右边是去掉4的) ,会发现从3往后每个数都比原来少了1
所以只需要把输入的数转成九进制,再分类输出就好了。
0 0
1 1
2 2
3 3
4 5 差1
5 6 差1
6 7 差1
7 8 差1
8 9 差1
正好九进制没有9
代码实现:
#include<iomanip>
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int s[1000005];
long long j=1;
void f(long long x){//十进制转九进制
while(x){
s[j]=x%9;
x/=9;
j++;
}
}
int main(){
long long n,a;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%lld",&a);
f(a);
for(int t=j-1;t>=1;t--){
if(s[t]>=4){//判断是否大于4
s[t]++;
}
printf("%d",s[t]);
}
cout<<"\n";
j=1;
}
return 0;
}
第四题:
题目描述:
小可是一个相信光的人,他最近在研究光与距离的问题。
给定一个 2*2 的网格,每个网格都有一盏路灯,且都在格点上,即:四盏路灯的位置分别是左上角, 右上角,左下角,右下角。
路灯都是需要耗电的,且耗电量与亮度有关,如果一盏路灯的耗电量是 x ,则它可以为他所在的格子提供 x 的亮度,并且为他相邻的格子提供 x/2下取整,为他对角的格子提供 x/4下取整 的亮度
某一个格子的亮度为四盏路灯为他提供的亮度之和
现在我们对四个格子的最低亮度提出了要求,我们想要让四个格子的亮度都达到标准。你可以将每一盏灯的耗电量调节为任何一个大于等于零的整数,为了省电, 你希望四盏灯的耗电量之和尽可能的小,请问四盏灯的最小耗电量之和是多小?
输入描述
输入四个整数:a,b,c,d,分别表示左上、右上、左下、右下 四个格子要求的亮度之和。
输出描述
输出一行一个整数表示四盏灯的最小耗电量之和。
输入样例1
50 24 25 12
输出样例1
50
样例说明1
左上角的位置的灯耗电量设置为 50,其它三个位置设为 0。即可满足亮度要求
输入样例2
8 8 8 8
输出样例2
15
样例说明2
4 盏灯耗电量依次为 4 3 4 4
数据描述
对于20%的数据:1≤a,b,c,d≤50
对于70%的数据:1≤a,b,c,d≤400
对于100%的数据:1≤a,b,c,d≤1500
思路:
二分枚举,套公式(详见注释)。
代码实现:
#include<iomanip>
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int a,b,c,d;
bool check(int mid){
for(int i=0;i<=a;i++){
for(int j=0;j<=d;j++){
int need=max(a-i-j/4,d-j-i/4);
if((mid-i-j)/2<need) continue;
int now=mid-i-j;//还有多少可以分配
int bneed=max(0,b-i/2-j/2);//b还需要多少
int cneed=max(0,c-i/2-j/2);//c还需要多少
int bb=max(0,(4*bneed-now)/3);//估算b大概区间
//p=b,q=c
//p+q/4=bneed, p+q=now
//p+q/4=bneed -> 得4p+q=4bneed
//4p+q=4beend -> 3p+now=4bneed
//p=
for(int k=max(0,bb-5);k<=min(now,bb+5);k++)
if(k+(now-k)/4>=bneed&&k/4+now-k>=cneed)
//左下提供+b>=b需要 左下>=需要
return true;;
}
}
return false;
}
int main(){
cin>>a>>b>>c>>d;
int l=0,r=a+b+c+d,ans=a+b+c+d;
while(l<=r){//枚举最小耗电量之和
int mid=(l+r)>>1;
if(check(mid)){
ans=mid;
r=mid-1;
}
else{
l=mid+1;
}
}
cout<<ans;
return 0;
}
四、赛后总结
错点有因为注释没删而不得分的,还有题不会的,数组下标变量搞错的。
以后一定注意:
1.认真检查。
2.多读几遍题。
3.多复习二维数组的行和列。
4.以后写完代码要检查检查是否把注释去掉了。