【无标题】

CSP-X模拟赛一胡时睿补题

日期:2023/10/01
学号:s06381
一:
总分数:
【爬楼梯stair】:15
【字符折线图sline】:0
【吉利数lucknum】:10
【路灯照明lighting】:0
二:
比赛过程:

第1题我先试了累加然后再除,但后来发现在每过1个平台时步数要重新计算,就改换成了边输入边累加,在到达平台后归0重新累加,直到这思路还是✔的;但是因为眼瞎我没看见“到达两个平台代表上了一层楼”,and:“从第一层出发”;故错了;第2题我的思路是用一个2维数组存储,通过1个累加器控制列数,但没有把字符数组完全初始化为“ ”(空格),加上输出思路不清晰,导致没有得分;第3题我是把1~这个数都遍历了一遍,数位分离把含有4的数的数量累加起来,再加上原数输出的;但代码实现时出了错,导致j一直增加;第4题都能看懂,纯属不会。

三:
比赛分析:
T1【爬楼梯stair】:
1题目大意:
小可和达达爬楼梯,小可和达达从第一层出发,记录了每一步迈出去的距离能够跨越多少个台阶和迈多少个台阶能够到达下一个平台。每次爬楼梯到达一个平台,就需要转身再爬,到达两个平台代表上了一层楼。计算现在小可和达达已经到达了多少层.
2、比赛中的思考:
我先试了累加然后再除,但后来发现在每过1个平台时步数要重新计算,就改换成了边输入边累加,在到达平台后归0重新累加,直到这思路还是✔的;但是因为眼瞎我没看见“到达两个平台代表上了一层楼”,and:“从第一层出发”;故错了;
3解题思路:
根据题目模拟即可。一步最多上一个平台。上两个平台才能上一个楼层。
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【字符折线图sline】
1题目大意:
我们根据一个字符串,可以画出一个折线图。从第二个字符开始,如果它比它的上一个字符大,那么就是上升的,画一个 / ;如果和上一个字符相同,那么画一个 - ;如果比比上一个字符小,那么就是下降的,画一个 \ 。并且上升的时候,要向上一行,下降的时候向下一行。具体例子如下:
字符串 hkrzyqqqmi :
  /\
 /  \
/    --
       \
        \
空白处使用空格填充,不要输出多余的空格。
2、比赛中的思考:
我的思路是用一个2维数组存储,通过1个累加器控制列数,但没有把字符数组完全初始化为“ ”(空格),加上输出思路不清晰,导致没有得分;
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【吉利数lucknum】:
1题目大意:
一个数字中如果有4这个数字就是不吉利的。相对的,其他的数字就是吉利的。想知道,第n个吉利的数字是多少。
2、比赛中的思考:
我是把1~这个数都遍历了一遍,数位分离把含有4的数的数量累加起来,再加上原数输出的;但代码实现时出了错,导致j一直增加;
3解题思路:
将十进制转换为九进制,对于数字中大于等于4的位置,加一输出即可。
因为相当于在十进制中,去掉了4这个数字,那么就是九进制。
九进制中的0对应十进制中的0,
九进制中的1对应十进制中的1,
九进制中的2对应十进制中的2,
九进制中的3对应十进制中的3,
九进制中的4对应十进制中的5,
九进制中的5对应十进制中的6,
九进制中的6对应十进制中的7,
九进制中的7对应十进制中的8,
九进制中的8对应十进制中的9,
九进制中没有4这个数字。
正好一一对应
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){
            a[cnt++]=k%9;
            k/=9;
        }
        for(int i=cnt-1;i>=0;i--){
            if(a[i]>=4) printf("%d",a[i]+1);
            else printf("%d",a[i]);
        }
        printf("\n");
    }
    return 0;
}

T4【路灯照明lighting】:
1题目大意:
给定一个2∗2的网格,每个网格都有一盏路灯,且都在格点上,即:四盏路灯的位置分别是左上角,右上角,左下角,右下角。
路灯都是需要耗电的,且耗电量与亮度有关,如果一盏路灯的耗电量是x,则它可以为他所在的格子提供x的亮度,并且为他相邻的格子提供⌊2⌋ ,为他对角的格子提供⌊4⌋的亮度,其中x表示对 向下取整。
某一个格子的亮度为四盏路灯为他提供的亮度之和,例如x左上角的灯耗电量为4,右上角的灯耗电量为 7,右下角的灯耗电量为 8,左下角的灯耗电量为 0,那么 左上角这个格子的亮度就是4 + ⌊ 27 ⌋ +⌊4/7⌋ +0

现在我们对四个格子的最低亮度提出了要求,我们想要让四个格子的亮度都达到标准。你可以将每一盏灯的耗电量调节为任何一个大于等于零的整数,为了省电, 你希望四盏灯的耗电量之和尽可能的小,请问四盏灯的最小耗电量之和是多小?
2、比赛中的思考:
题都能看懂,纯属不会。
3、解题思路:
本题显然具有二分性,考虑二分答案。
假设总共有mid的耗电量可以分配给四盏灯,我们考虑如何分配:
枚举对角线的两盏灯的耗电量,假设枚举的是左上角和右下角那么我们可以发现,右上角这个格子当前亮度为⌊2/a+2/b⌋,左下角的格子的亮度也一样。我们可以算出这两个格子的亮度与需求的差值,再将mid − a − b
的耗电量分配给这两盏灯。
一种减少写代码细节的小技巧是:算出左下角格子的大致耗电量,然后用for循环在估计值的附近枚举即可,这样就不需要判断边界条件了。
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);
            // b还需要多少
            int cneed = max(0, c - i / 2 - j / 2);
            // c还需要多少
            int bb = max(0, (bneed - now / 4) * 4 / 3);
            //估算b大概区间
            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;
}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值