CSP-J模拟赛一刘皓铭 补题日期:2023.10.2 学号:S12418

一总分数:
T1【爬楼梯(stair)】:100 
T2【字符折线图(sline)】:10
T3【吉利数(lucknum)】:60
T4【路灯照明(lighting)】:10
二、比赛过程

第一道题实属水题,只要看懂题面就可以得满分,创建两个变量,存放步数和一层的高度,再把输入的步长累加起来,输出现在的层数即可。很轻送的得了满分。

第二道题我不会输出换行的起伏,本想蒙上一些程序得分,结果之对了10%。
第三道题我采用暴力枚举,但最后20分用暴力枚举发现做不了,所以得了60分。
第四道题超出了我学的知识范围

三、比赛分析
T1【爬楼梯(stair)】:
1、题目大意
通过走的步数和楼层的高度计算现在小可和达达在第几层楼。

2、比赛中的思考
我用了累加到楼层高度,再把计数器++,最后把计数器/2的结果强转成为int类型。

3、解题思路
循环t次输入n再累加起来/2,把结果取下整输出即可。

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、题目大意
根据字符串的变化来输出,递增输出“/”,递减输出“\”,相等则输出“-”。

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【吉利数(lucknum)】:
1、题目大意
寻找第n个不含4的数。
2、比赛中的思考
我直接采用暴力枚举,把数传到函数里判断是否含有4,若没有,接着遍历,若含有则把要找的数增加1...直至找到。

3、解题思路
将十进制转换为九进制,对于数字中大于等于4的位置,加一输出即可。
因为相当于在十进制中,去掉了4这个数字,那么就是九进制。
九进制中的 0对应十进制中的 0,
九进制中的 1对应十进制中的 1,
九进制中的 2对应十进制中的 2,
九进制中的 3对应十进制中的 3,
九进制中的 4对应十进制中的 5,
九进制中的 5对应十进制中的 6,
九进制中的 6对应十进制中的 7,
九进制中的 7对应十进制中的 8,
九进制中的 8对应十进制中的 9,
九进制中没有九这个数字。
正好一一对应。
时间复杂度O(Tlogn)

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的格子中,左上角的亮度是左上角+右上角/2+左下角/2+右下角/4,每个区域要保持标准亮度,问:要供电多少?

2、比赛中的思考
这道题不在我的知识范畴之内,运用的二分答案我还没学,我尝试了多种方法,都无法代替二分答案。

3、解题思路
本题显然具有二分性,考虑二分答案。
假设总共有m的耗电量可以分配给四盏灯,我们考虑如何分配:
枚举对角线的两盏灯的耗电量,假设枚举的是左上角和右下角 。那么我们可以发现,右上角这个格子当前亮度为a/2+b/2左下角的格子的亮度也一样。我们可以算出这两个格子的亮度与需求的差值,再将m-a-b的耗电量分配给这两盏灯。

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、付费专栏及课程。

余额充值