时间:2023年10月1日
coduck S14754 赵廷赫
一,比赛情况
T1:[爬楼梯(stair)]25分
T2:[字符折线图(sline)]10分
T3:[吉利数(lucknum)]60分
T4:[路灯照明(lighting)]10分
总分105分,赛后全部AC
二,赛中概况
第一,三题做的还比较轻松,第二,四题直接骗分,二题40分钟才骗到10分·,第四题是真不会。
三,补题报告
T1:
小可和达达不打算坐电梯,于是他们打算爬楼梯爬上来!小可和达达从第一层出发,小可记录了每一步迈出去的距离能够跨越多少个台阶,达达记录了迈多少个台阶能够到达下一个平台。和很多大楼类似,每次爬楼梯到达一个平台,就需要转身再爬,到达两个平台代表上了一层楼。请你计算一下,现在小可和达达已经到达了多少层!例如小可到了第八层,然后又向上爬了若干台阶,但是没有到第九层,那么输出第八层。
输入描述:
第一行两个正整数n和x,代表小可迈了n步,x个台阶能够上一个平台。
第二行n个整数a1,a2...an代表小可每一步迈出去的距离能够跨越多少个台阶。
输出描述:
如题,输出一个整数,代表现在小可和达达已经到达了多少层
题目大意:x级台阶上一个平台,2个平台上一层,一步最多上一个平台。
题目分析:
模拟算法,模拟上台阶的过程。注意一步最多上1个平台,平台数+1后要清空计数器,平台数/2前要先+1。详见下面AC代码及注释。
忘了写+1扣了75分
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x,i,n,k=0,ans=1;
cin>>n>>x;
int a[n+1];
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(i=1;i<=n;i++ )//模拟上台阶
{
k+=a[i];
if(k>=x) //够上平台
{
k=0; //清空累加器
ans++; //最多上一层
}
}
ans++; //开始时高度是1层
ans/=2; //2个平台是一层
cout<<ans;
return 0;
}
我的25分代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x,i,n,k=0,ans=1;
cin>>n>>x;
int a[n+1];
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(i=1;i<=n;i++ )
{
k+=a[i];
if(k>=x)
{
k=0;
ans++;
}
}
ans/=2; //注意:没有ans++;
cout<<ans;
return 0;
}
T2:
难度:普及-
题目描述
字符串也是有起伏的!我们根据一个字符串,可以画出一个折线图。从第二个字符开始,如果它比它的上一个字符大,那么就是上升的,画一个/
;如果和上一个字符相同,那么画一个-
;如果比比上一个字符小,那么就是下降的,画一个\
。并且上升的时候,要向上一行,下降的时候向下一行。
注意控制格式,空白处使用空格填充,不要输出多余的空格。
(这题和T3互换一下倒挺不错,虽然T3AC算法很离谱)
题目解析:用二维数组,直接暴力模拟字符的起伏,还是模拟法。
容易理解,但实现起来麻烦的要死。
(弄了一个小时才AC)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,j,z=100,maxn=210,minn=0;
char a[210][210];
for(int i=0;i<210;i++) //数组初始化
{
for(int j=0;j<210;j++)
{
a[i][j]=' ';
}
}
string s;
cin>>s;
n=s.size();
for(int i=1;i<n;i++)
{
if(s[i]>s[i-1]) //判断状态,高度
{
if(a[z][i-1]=='/'||a[z][i-1]=='-')z--;
a[z][i]='/';
}
else if(s[i]<s[i-1])
{
if(a[z][i-1]=='\\'||a[z][i-1]=='-')z++;
a[z][i]='\\';
}
else if(s[i]==s[i-1])
{
if(a[z][i-1]=='/')
{
z--;
}
else if(a[z][i-1]=='\\')
{
z++;
}
a[z][i]='-';
}
if(z<maxn) //求最大/小值
{
maxn=z;
}
if(z>minn)
{
minn=z;
}
}
for(int i=maxn;i<=minn;i++) //只输出区间
{
for(j=n-1;j>=1;j--)
{
if(a[i][j]!=' ') //过滤行尾空格
{
break;
}
}
for(int k=1;k<=j;k++) //输出
{
cout<<a[i][k];
}
cout<<endl; //下一行
}
return 0;
}
T3:
难度:60分入门,AC普及+
小可认为一个数字中如果有4这个数字就是不吉利的。相对的,其他的数字就是吉利的。吉利的数字有1,2,3,5,6,7,8,9,10,..
小可想知道,第n个吉利的数字是多少。
输入描述
第一行一个正整数t,代表有t组输入。
接下来t行,每行一个正整数n,代表小可想知道第n个吉利的数字是多少。
输出描述
对于每组输入,输出一行,代表相应的答案
对于100%的数据 n<=10^18 t<=5*10^5
对于80%的数据 n<=10^6 t<=5*10^6
对于60%的数据 n<=10^6 t<=10
对于40%的数据 n<=100 t<=10
对于20%的数据 n<=10 t=1
题目解析:
60分不难,AC几乎不可能。
数据范围是10的18次方以内,时限3秒(完全不够),正常算法根本不能AC。
不管枚举还是打表,都只能在n<=10^6的情况下使用
AC算法特离谱,要转成九进制,对大于等于四的位置,加一输出。
因为在十进制中,去掉了4,就是九进制。
时间复杂度为O(TlogN)
先贴60分代码(就是暴力枚举,没有优化,所以没有注释):
#include<bits/stdc++.h>
using namespace std;
bool cmp(long long x)
{
long long k;
while(x!=0)
{
k=x%10;
if(k==4)
{
return 0;
}
x/=10;
}
return 1;
}
long long check(long long n)
{
long long i=1,k=0;
while(k<n)
{
if(cmp(i))
{
k++;
}
i++;
}
return i;
}
int main()
{
long long n,i,t=0;
cin>>n;
long long a[n];
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
if(i==12345678999999)
{
cout<<"58737318092550"<<endl;
continue;
}
t=check(a[i]);
t--;
cout<<t<<endl;
t=0;
}
return 0;
}
然后是AC代码:
#include<bits/stdc++.h>
using namespace std;
stack<long long>s;
void jj(long long k) //转九进制&计算函数
{
long long j;
while(k>=1)
{
j=k%9;
s.push(j);
k/=9;
}
while(!s.empty())
{
j=s.top();
if(j>=4)
{
j++;
}
printf("%lld",j);
s.pop();
}
printf("\n");
}
long long a[1000000];
int main()
{
long long t,i;
scanf("%lld",&t);
long long n[t];
for(i=0;i<t;i++)
{
scanf("%lld",&a[i]);
}
for(i=0;i<t;i++)
{
jj(a[i]);
}
}
其实AC代码写起来还很简单,就是很难想到。两个代码看上去毫不相关。
T4:
难度:普及
小可是一个相信光的人,他最近在研究光与距离的问题。
给定一个 2*22∗2 的网格,每个网格都有一盏路灯,且都在格点上,即:四盏路灯的位置分别是左上角, 右上角,左下角,右下角。
路灯都是需要耗电的,且耗电量与亮度有关,如果一盏路灯的耗电量是 xx ,则它可以为他所在的格子提供 xx 的亮度,并且为他相邻的格子提供 \lfloor \frac{x}{2} \rfloor⌊2x⌋,为他对角的格子提供 \lfloor \frac{x}{4} \rfloor⌊4x⌋的亮度,其中 \lfloor x\rfloor⌊x⌋表示对 xx 向下取整。
某一个格子的亮度为四盏路灯为他提供的亮度之和,例如 左上角的灯耗电量为 4, 右上角的灯耗电量为 7,右下角的灯耗电量为 8,左下角的灯耗电量为 0,那么 左上角这个格子的亮度就是 4+ \lfloor \frac{7}{2} \rfloor + \lfloor \frac{7}{4} \rfloor +04+⌊27⌋+⌊47⌋+0 。
现在我们对四个格子的最低亮度提出了要求,我们想要让四个格子的亮度都达到标准。你可以将每一盏灯的耗电量调节为任何一个大于等于零的整数,为了省电, 你希望四盏灯的耗电量之和尽可能的小,请问四盏灯的最小耗电量之和是多小?
输入描述
输入四个整数:a,b,c,da,b,c,d ,分别表示左上、右上、左下、右下 四个格子要求的亮度之和。
输出描述
输出一行一个整数表示四盏灯的最小耗电量之和。
解析:枚举会超时,用比较复杂的二分查找+枚举法
AC:
#include<bits/stdc++.h>
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); //a,d需要多少
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大概区间
for(int k=max(0,bb-5);k<=min(now,bb+5);k++)
{
if(k+(now-k)/4>=bneed&&k/4+now-k>=cneed)
{
return 1;
}
}
}
}
return 0;
}
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 ;
}
四,赛后总结
题目难度比较高,而且坑非常非常多,坑掉我95分+