CSP-X模拟赛一沙煜博补题

一:
总分数:
T1【爬楼梯】:5
T2【字符折线图】:0
T3【吉利数】:0
T4【路灯照明】:0

二、比赛过程

第一道 粗心大意,一步最多上一个平台。上两个平台才能上一个楼层。
第二道 思路错误,注意到我们会向上一行输出,这在我们程序中只使用 等很难实现。我们可以开一个大的二维数组,以二维数组最中间的一行作为水平线,这样的话我们就可以很方便地向上或者向下一行移动。最后去掉多余的行和列,输出二维数组即可。
当然要注意细节,需要记录一下上一次的操作,从而决定行的变化。
第三道 直接进行暴力枚举即可。从 开始枚举,碰到吉利数,计数器加一。当计数器等于 时,输出结果。时间复杂度O(Tn)
第四道 不能理解题目意思,本题显然具有二分性,考虑二分答案。
假设总共有 的耗电量可以分配给四盏灯,我们考虑如何分配:
枚举对角线的两盏灯的耗电量,假设枚举的是 左上角 和右下角 。那么我们可以发现,右上角这个格子当前亮度为 ,左下角的格子的亮度也一样。我们可以算出这两个格子的亮度与需求的差值,再将
的耗电量分配给这两盏灯。
一种减少写代码细节的小技巧是:算出左下角格子的大致耗电量,然后用 循环在估计值的附近枚举即可,这样就不需要判断边界条件了。

三、比赛分析

T1【爬楼梯】:

1.题目大意

小可和达达从第一层出发,小可记录了每一步迈出去的距离能够跨越多少个台阶,达达记录了迈多少个台阶能够到达下一个平台。例如小可到了第八层,然后又向上爬了若干台阶,但是没有到第九层,那么输出第八层。一步最多上一个平台。上两个平台才能上一个楼层。

2.比赛中的思考

这道题可以用累加器累加迈出去的距离,如果超过平台,则归零,计数器自增。(((m -__-)m

3、解题思路
这道题可以用累加器累加迈出去的距离,如果超过平台,则归零,计数器自增,重复执行。最后计数器/2+1。

4.AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,x,tmp,sum,cnt;
int main(){
    scanf("%d%d",&n,&x);
    for(int i=1;i<=n;i++){
        scanf("%d",&tmp);
        if(sum+tmp>=x){
            sum=0;
            cnt++;
        }
    }
        else sum+=tmp;
    }
    printf("%d\n",1+int(cnt/2));
    return 0;
}

T2【字符折线图】:

1.题目大意

从第二个字符开始,如果它比它的上一个字符大,那么就是上升的,画一个/;如果和上一个字符相同,那么画一个-;如,那么就是下降的,画一个\。并且上升的时候,要向上一行,下降的时候向下一行。具体例子如下:

2.比赛中的思考

如果一个字符比它的上一个字符大画一个/,如果和上一个字符相同画一个-,果比上一个字符小画一个\。
3、解题思路

注意到我们会向上一行输出,这在我们程序中只使用cin,cout等很难实现。我们可以开一个大的二维数组,以二维数组最中间的一行作为水平线,这样的话我们就可以很方便地向上或者向下一行移动。最后去掉多余的行和列,输出二维数组即可。
当然要注意细节,需要记录一下上一次的操作,从而决定行的变化。
4.AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
char s[105];
int g[405][405];//1 - 2 / 3 down
int main(){
scanf("%s",s);
int n=strlen(s),line=200,pre=0;
for(int i=1;i<n;i++){
if(s[i]==s[i-1]){
if(pre==2) line++;
else if(pre==3) line--;
g[line][i]=pre=1;
}
else if(s[i-1]<s[i]){
if(pre!=3) line++;
g[line][i]=pre=2;
}
else{
if(pre!=2) line--;
g[line][i]=pre=3;
}
}
for(int i=0;i<405;i++){
for(int j=204;j>0;j--){
if(g[i][j]){
g[i][0]=j;
break;
}
}
}
int bg=404,ends=0;
while(!g[bg][0]) bg--;
while(!g[ends][0]) ends++;
for(int i=bg;i>=ends;i--){
for(int j=1;j<=g[i][0];j++){
if(!g[i][j]) printf(" ");
else if(g[i][j]==1) printf("-");
else if(g[i][j]==2) printf("/");
else printf("\\");
}
printf("\n");
}
return 0;
}

T3【吉利数】:

1.题目大意

数字中如果有4这个数字就是不吉利的。相对的,其他的数字就是吉利的。如:

2.比赛中的思考

直接进行暴力枚举即可。从 开始枚举,碰到吉利数,计数器加一。当计数器等于 时,输出结果。时间复杂度O(Tn);

3、解题思路

将十进制转换为九进制,对于数字中大于等于 的位置,加一输出即可。
因为相当于在十进制中,去掉了 这个数字,那么就是九进制。
九进制中的1 对应十进制中的 1,
九进制中的2 对应十进制中的 2,
九进制中的3 对应十进制中的 3,
九进制中的4 对应十进制中的 5,
九进制中的5 对应十进制中的 6,
九进制中的6 对应十进制中的 7,
九进制中的7 对应十进制中的 8,
九进制中的8 对应十进制中的 9,
九进制中的9 对应十进制中的 10,
九进制中没有九这个数字。
正好一一对应。

4.AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll t,k;
int a[30],cnt;
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&k);
cnt=0;
while(k){
}
for(int i=cnt-1;i>=0;i--){
}
printf("\n");
}
return 0;
}

T4【路灯照明】:

1.题目大意

2.比赛中的思考

直接枚举每一盏灯的耗电量,然后按照公式计算每一个格子的亮度是否符合要求。
时间复杂度:O(n⁴)。

3、解题思路

枚举三盏灯的耗电量,计算出此时每个格子的亮度,算出每个格子当前亮度与需求亮度的差值,这个差值由第四盏灯来填补。即枚举好三盏灯之后,我们可以 O(1) 算出第四盏灯的最低耗电量。
时间复杂度:O(n³)。

4.AC代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 100005
#define M 2000005
#define mod 1000000007
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<int, int>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
//#pragma GCC optimize("O3")
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
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);
int cneed = max(0, c - i / 2 - j / 2);
int bb = max(0, (bneed - now / 4) * 4 / 3);
for (int k = max(0, bb - 5); k <= min(now, bb + 5); k++) //枚举b
if (k + (now - k) / 4 >= bneed && k / 4 + now - k >= cneed)
return true;
}
}
return false;
}
int main()
{
CLOSE
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 << endl;
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值