2019牛客暑期多校第六场题解ABDJ

A.Garbage Classification

传送门

题意:给你两个串,第一个串s由小写字母组成,第二个串t由dwh组成,长度为26,分别表示字母a到z代表的字符。现在要你判断:

  • 如果字符串中‘h’的数量至少占s串长度的25%,输出  “Harmful”
  • 如果字符串中‘h’的数量最多占s串长度的10%,输出  “Recyclable”
  • 否则,如果字符串中‘d’的数量至少是‘w’的两倍,输出 “Dry”
  • 否则输出 “Wet”

题解:判断即可。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e3 + 10;
char s[N],t[30];
int main() {
    int T, cnt = 1;
    for (scanf("%d",&T);T--;) {
        scanf("%s%s",s,t);
        int len = strlen(s);
        printf("Case #%d: ", cnt++);
        int num[30] = {0},w = 0, h = 0, d = 0;
        for (int i = 0; i < len; i++) num[s[i]-'a']++;
        for (int i = 0; i < 26; i++) {
            if (t[i] == 'w') w+=num[i];
            if (t[i] == 'h') h+=num[i];
            if (t[i] == 'd') d+=num[i];
        } 
        if (h*4 >= len) printf("Harmful\n");
        else if (h*10 <= len) printf("Recyclable\n");
        else if (d >= 2 * w) printf("Dry\n");
        else printf("Wet\n");
    }
    return 0;
}
View Code

 

 

B.Shorten IPv6 Address

传送门

题意:给你一个128长度的二进制串,要转化成IPv6地址的形式,例如 “0:0:123:4567:89ab:0:0:0”(忽略前导0),若有连续两个及以上的0,那么可以把那一段写成“::”,但是注意一个地址中最多有1个“::”。要求输出最短的形式,如果长度相同输出字典序最小的结果。

题解:显然我们将最长连续0的那一段转化为“::”比转化把它短的要优,当有长度相同的连续0时,显然转化中间的比转化两边的优(转化中间的比转化两边的长度要少1),相同且都在首尾或者且都在中间时,显然选转化后面那个更优(‘0’字典序比‘:’小)。

       可以将二进制转化为十六进制比较也可以转化为十进制比较,因为C++可以直接%x输出十六进制数所以用十进制比较方便。

       想法是对的但是写丑了WA了一下午嘤嘤嘤(╥╯^╰╥)

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
#define maxn 2
const int N = 1e5 + 10;
char s[200];
int cel(int id) {
    int x = 0;
    for (int i = id; i < id + 16; i++) x = x * 2 + s[i]-'0';
    return x;
}
int main() {
    int T,t=1;
    for (scanf("%d",&T);T--;) {
        scanf("%s",s);
        int pos = -1,num = 1;
        int a[10] = {0};
        for (int i = 0; i < 128; i+=16) 
            a[i/16] = cel(i); 
        for (int i = 7; i >= 0; i--) {
            int cnt = 0;
            if (!a[i]) {
                while(i>=0 && !a[i]) i--,cnt++;
                i++;
                if (cnt == num && pos+num == 8 && i) pos = i,num = cnt;
                if (cnt > num) pos = i,num = cnt;
            }
        }
        printf("Case #%d: ",t++);
        for (int i = 0; i < 8; i++) {
            if ( i == pos) {
                if (pos == 0) printf(":");
                printf(":");
                i+=num-1;
            }else {
                printf("%x",a[i]);
                if (i!=7) printf(":");
            }
        }
        printf("\n");
    }
    return 0;
}
十进制
#include <bits/stdc++.h>
#define ll long long
using namespace std;
#define maxn 2
const int N = 1e5 + 10;
char s[200],ans[10][10];
bool _is0[10];
char cel(int id) {
    int x = 0;
    for (int i = id; i < id + 4; i++) x = x * 2 + s[i]-'0';
    if (x < 10) return x+'0';
    return x-10+'a';
}
bool judge0(int x){
    int i;
    for (i = 0; ans[x][i+1]; i++) {
        if (ans[x][i] != '0') return false;
        for(int j = i; ans[x][j]; j++) ans[x][j] = ans[x][j+1];
            i--;
    }
    return ans[x][i]=='0';
}
int main() {
    int T,t=1;
    for (scanf("%d",&T);T--;) {
        scanf("%s",s);
        int pos = -1;
        int num = 1;
        for (int i = 0, j = 0,k = 0; i < 128; i+=4) {
            ans[k][j++] = cel(i);
            if(j == 4) ans[k][j] = '\0',j = 0,_is0[k]=judge0(k),k++;
        }
        for (int i = 7; i >= 0; i--) {
            int cnt = 0;
            if (_is0[i]) {
                while(i>=0 && _is0[i]) i--,cnt++;
                i++;
                if (cnt == num && pos+num == 8 && i) pos = i,num = cnt;
                if (cnt > num) pos = i,num = cnt;
            }
        }
        printf("Case #%d: ",t++);
        for (int i = 0; i < 8; i++) {
            if ( i == pos) {
                i+=num-1;
                if (pos == 0) printf(":");
                printf(":");
            }else {
                printf("%s",ans[i]);
                if (i!=7) printf(":");
            }
        }
        printf("\n");
    }
    return 0;
}
十六进制

 

 

D.Move

传送门

题意:有n件物品,每件物品体积为vi,用k个相同大小的盒子来装他们,问盒子最小体积可以为多少。

题解:我们知道盒子最小体积为max(a[n],sum/k),我们可以从最小可能的体积开始枚举,一个个来判断。数据都很小不超过1000所以不会T。

那我们怎么判断呢?我们可以把物品按体积由大到小依次放进盒子里,能放得下就放,否则就放下一个,放不进就表示盒子小了,否则就是答案。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3 + 10;
const ll INF = 1ll<<60;
int a[N],n,m,b[N];
bool check(int x){
    for (int i = 1; i <= m; i++) b[i] = x;
    for (int i = n; i >= 1; i--) {
        bool fg = 0;
        for (int j = 1; j <= m; j++)
            if (a[i] <= b[j]) {
                b[j] -= a[i];
                fg = 1;
                break;
            }
        if (!fg) return false;
    }
    return true;
}
int main() {
    int T, cnt = 1;
    for (scanf("%d",&T);T--;) {
        int sum = 0;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        sort(a+1,a+1+n);
        for (int i = max(a[n],sum/m);;i++)
            if (check(i)) {
                printf("Case #%d: %d\n", cnt++,i);
                break;
            }
    }
    return 0;
}
View Code

 

 

J.Upgrading Technology

传送门

题意:有n个技能,每个技能都有m个等级(一开始等级都为0),每升一级需要花费C(i,j)(只能一级一级升),如果每个技能都达到i级,可以得到di的利润。可以不升级利润为0,。问能得到的最大利润为多少。

题解:我们可以用前缀和维护每个技能升级的最小花费,倒着更新一遍最小值。然后把每个技能升级到i(可能是以上)所需的最小花费加起来,然后我们维护下每个等级利润d的前缀和,技能最小等级为i时的利润为d的前缀和 - 每个技能升级到i所需的最小花费。这里要注意两个点,一是我们前面维护的每个技能升级到i(可能是以上)所需的最小花费可能把技能等级更新到了i以上,若每个技能等级都在i以上,那么获得的利润就不是d1~i,而是当前最小技能j的利润和d1~j,所以我们需要保留一个升级到i所需花费与我们维护的最小值差最小的来确保最低等级为i且获得的利润最大。二是注意可能存在有技能等级为0,其他技能升级花费为负的情况。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3 + 10;
const ll INF = 1ll<<60;
ll a[N][N],c[N][N],b[N];
int main() {
    int T, cnt = 1,n,m;
    for (scanf("%d",&T);T--;) {
        scanf("%d%d",&n,&m);
        memset(a,0,sizeof(a));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                scanf("%lld",&a[i][j]);
                a[i][j] += a[i][j-1];
                c[i][j] = a[i][j];
            }
            a[n+1][m] += a[i][m];
            for (int j = m-1; j >= 0; j--){
                a[i][j] = min(a[i][j],a[i][j+1]);
                a[n+1][j] += a[i][j];
            }
        }
        b[0] = 0;
        for (int i = 1; i <= m; i++) {
            scanf("%lld",&b[i]);
            b[i] += b[i-1];
        }
        ll ans = 0;
        for (int i = 0; i <= m; i++) {
            int pos = -1;
            ll mind = INF,d;
            for (int j = 1; j <= n; j++) {
                d = c[j][i] - a[j][i];
                if (d < mind) {
                    mind = d;
                    pos = j;
                }
            }
            ans = max(ans,b[i]-a[n+1][i]+a[pos][i]-c[pos][i]);
        }
        printf("Case #%d: %lld\n", cnt++,ans);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/l999q/p/11296232.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值