牛客周赛 Round 54
A 清楚姐姐的糖葫芦
链接:https://ac.nowcoder.com/acm/contest/87303/A 来源:牛客网
题目描述
清楚年少时,随家人各处跑商。一日,车马歇于野外树林歇息,遇一老妪叫卖糖葫芦:“三文一串,十文三串……”
清楚算了算,觉其价高,非善贾也,遂摇首拒之:“NO喵”。
但是很想吃糖葫芦,于是决定自己动手。
清楚姐姐很喜欢串糖葫芦,现在给你一个糖葫芦字符串,请你数一下有多少颗糖葫芦。
糖葫芦字符串是一个只包含字符 o 和字符 − 的字符串,其中,o 代表糖葫芦,− 代表木棍。
输入描述:
在一行上输入一个长度不超过 103 且只由字符 o 和 − 构成的字符串 𝑠 ,代表糖葫芦串。
输出描述:
在一行上输出一个整数,代表糖葫芦的数量 。
示例1
输入
–ooo–
输出
3
题解
数个数,不解释
#include<bits/stdc++.h>
using namespace std;
string s;
int ans;
int main(){
int i,j,k;
cin>>s;
for(i=0;i<s.length();i++)
if(s[i]=='o')ans++;
cout<<ans<<endl;
return 0;
}
B 清楚姐姐买竹鼠
链接:https://ac.nowcoder.com/acm/contest/87303/B 来源:牛客网
题目描述
清楚十五六岁时进京赶考,途经一处山村,忽见一铺专卖竹鼠。竹鼠很贵,但是竹鼠很可爱!
先等等。遂清点囊中碎银。可以上了。它说,可以上了!
清楚姐姐买竹鼠,𝑎 元可以买一只竹鼠,𝑏 元可以买三只竹鼠,问至少买 𝑥 只竹鼠要花多少钱。
输入描述:
第一行输入三个整数 𝑎,𝑏 和 𝑥 (1≤𝑎,𝑏,𝑥≤109) ,其含义已在题目中声明。
输出描述:
在一行上输出一个整数表示至少买 𝑥 只竹鼠要花多少钱。
示例1
输入
4 10 10
输出
34
说明
花费 3×𝑏=30元买9 只竹鼠,再花费 1×𝑎=4元买 1 只竹鼠,共花费 34 元。我们可以证明,没有更优的购买方式。
题解
这设计多少有点反人类,竟然有可能b小于a,哪家开的店我去蹭。。。
言归正传,讨论下题目就行,具体看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a,b,x;
signed main(){
int i,j,k;
cin>>a>>b>>x;
if(a*3<=b){
printf("%d\n",a*x);
}
else {
int s1=x%3,s2=x/3;
printf("%d\n",min((s2+1)*b,s1*a+s2*b));
}
return 0;
}
C 竹鼠饲养物语
链接:https://ac.nowcoder.com/acm/contest/87303/C 来源:牛客网
题目描述
清楚进店,见一老妪端坐其中,竟是当年卖糖葫芦那厮。
老妪也认出了清楚,率先开口:“有缘千里来相会,你买下竹鼠,我带你去探寻宝物”。
言毕,见清楚执意要买,又添一句:“还需出饲料钱。”
鼠鼠快速成长饲料一共分为 𝑚 个等级,初始时全部竹鼠都是零级竹鼠,投喂一袋“鼠鼠快速成长饲料 I ”可以升级为一级竹鼠,继续投喂“鼠鼠快速成长饲料 II ”可以升级为二级竹鼠,……。需要注意的是,你不能越级投喂,例如,向零级竹鼠投喂“鼠鼠快速成长饲料 II ”没有任何效果。
清楚一共有 𝑛 袋饲料和无限多的零级竹鼠,问最多可以进行多少次有效投喂。
输入描述:
第一行上输入两个整数 𝑛,𝑚 (1≤𝑛≤105; 1≤𝑚≤109) 代表饲料数量和饲料等级数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑚)代表每一袋饲料的等级。
输出描述:
在一行上输出一个整数,代表清楚至多进行的有效投喂次数。
示例1
输入
7 5
1 1 1 2 2 3 5
输出
6
说明
● 可以将第一只竹鼠直接升到三级,此时剩下4袋饲料 {1,1,2,5} ;
● 将第二只竹鼠升到两级,此时剩下 2 袋饲料 {1,5};
● 将第三只竹鼠升到一级,此时剩下最后 1 袋饲料 {5} ;
● 最后一袋饲料无法使任何竹鼠升级,故最终使用了 6 袋饲料。
示例2
输入
6 114514
1 1 4 5 1 4
输出
3
题解
这是啥玩意呢?你削微分析下题干,题目中给的m就是唬你玩的
讲下思路:
首先你的粮食最大值只有105个,所以最多最多升到105级,剩下的就是浪费的。
因此你记录的时候只需要记录105内的粮食。
然后就是讨论每个粮食能吃多少了,这玩意,前缀最小值。理由?你家老鼠不能越级,天赋不够!
最火谴责下那个万恶的96%哈,记得long long
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[100005];
int minn=100000000,ans;
signed main(){
int i,j,k;
cin>>n>>m;
for(i=1;i<=n;i++){
int x;cin>>x;
if(x<100000)a[x]++;//大于10^5没必要统计了
}
for(i=1;a[i]>0;i++)
{
minn=min(a[i],minn);
ans+=minn;
}
cout<<ans<<endl;
return 0;
}
D 清楚姐姐跳格子
链接:https://ac.nowcoder.com/acm/contest/87303/D 来源:牛客网
题目描述
老妪遂递一羊皮卷轴,上面什么都没有,清楚欲问,老妪却缄口不言。
清楚性格刚直,放下鼠资,正欲再问,忽觉眼前一花,老妪和店铺却都消失不见,唯卷轴与竹鼠。“怪哉”,清楚回头走,见到地上有一些格子。
清楚正在玩跳格子游戏。地上有 𝑛 个格子,清楚一开始在 1 号格子,目标是 𝑛 号格子。第 𝑖 个格子上有一个数字 𝑎𝑖 ,清楚在这个格子上可以往左右两边选一个方向,然后选择 𝑎𝑖 的一个正整数因子作为长度,进行一次跳跃,但是不可以跳出边界。
请问清楚最少跳多少步,就可以到达 𝑛 号格子。
输入描述:
第一行输入一个整数𝑛 ( 1≤𝑛≤103) 代表格子数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,…,𝑎𝑛 ( 1≤𝑎𝑖≤1018) 代表格子上的数字。
输出描述:
在一行上输出一个整数,代表到达终点需要的最少步数 。
示例1
输入
5
2 3 1 5 4
输出
2
说明
在1号节点 ,选择𝑎1的因子1,往右跳1步,到达2号节点。
在2号节点 ,选择𝑎2的因子3,往右跳3步,到达5号节点。
题解
简单的BFS,搜索出所有的可以到达的位置
或者Dijsktra,构建成一棵树,跑一遍最短路
#include <bits/stdc++.h>
using namespace std;
long long a[1005];
int main()
{
int i,j,n;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
queue<long long> q;
vector<int> d(n,-1);
d[0]=0;
q.push(0);
while(q.size())
{
int now=q.front();
q.pop();
for(j=0;j<n;j++)
{
if(d[j]==-1&&a[now]%abs(now-j)==0)
{
d[j]=d[now]+1;
q.push(j);
}
}
}
cout<<d.back()<<endl;
return 0;
}
E 清楚姐姐的布告规划
链接:https://ac.nowcoder.com/acm/contest/87303/E
来源:牛客网
题目描述
待榜之期,漫长如年。为自己和竹鼠们的生计,清楚在京师寻得一份张贴布告之差事,既可糊口,亦广交良朋,共商寻宝大业。
某日,清楚在张贴布告时,浆糊不慎落于羊皮卷上,湿透之处,竟现复杂图形……
清楚需要在长度为 𝑛 个单位的布告板上张贴至多 𝑛 张布告,第 𝑖 张布告的长度为 𝑎𝑖 个单位,如果选择第 𝑖 张贴布告时需要满足:
● 第 𝑖 张布告必须要覆盖掉布告板的第 𝑖 个位置;
● 布告不能够相互重叠,但是可以紧贴。
清楚想要知道自己按照要求,至少需要张贴几张布告,才能将布告板贴满。
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 𝑇 (1≤𝑇≤100) 代表数据组数,每组测试数据描述如下:
第一行输入一个整数 𝑛 (1≤𝑛≤5000)代表布告板的长度(同时也代表布告的张数)。
第二行输入 𝑛 个整数 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑛) 代表每一张布告的长度。
除此之外,保证所有的𝑛 之和不超过 5000 。
输出描述:
对于每一组测试数据,在一行上输出一个整数代表清楚至少需要贴的布告数量;如果无解,直接输出 −1 。
示例1
输入
2
4
1 2 2 3
3
2 2 2
输出
2
-1
说明
对于第一组测试数据,有两种合法的选择方式:
● 贴第一、四张布告;
● 贴第二、三张布告;
对于第二组测试数据,无论怎么张贴都会有重叠部分。
题解
看起来唬人。。。实际就是01背包,板子题,不解释
#include<bits/stdc++.h>
using namespace std;
int T,n,a[5005],dp[10005];
int main(){
int i,j,k;
cin>>T;
while(T--){
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i],dp[i]=1e9;
dp[0]=0;
for(i=1;i<=n;i++){
for(j=max(0,i-a[i]);j<i;j++){
dp[j+a[i]]=min(dp[j+a[i]],dp[j]+1);
}
}
if(dp[n]==1e9) dp[n]=-1;
cout<<dp[n]<<endl;
}
return 0;
}
F 竹鼠,宝藏与故事
链接:https://ac.nowcoder.com/acm/contest/87303/F
来源:牛客网
题目描述
收工回店,清楚开始仔细研究这些图形。竹鼠忽开口言:“蒙君饱腹之恩,吾等当助君得宝。“言罢,摇身一变,化作数道白光没入轴中,清楚定睛一看,方觉卷轴乃一微型迷宫也。
迷宫曲折,然竹鼠数量众多、各行其道,不消片刻,白光再现,宝物尽数被带出。
𝑛×𝑚的迷宫中有无数珍宝,左上角为迷宫的起点,右下角为终点。我们使用数字 −1 标记这个格子无法被通过;使用自然数来代表这个格子上宝藏的珍惜程度(数字为 0 即代表该位置上不存在宝藏)。现在,你需要找出所有从起点出发、直达终点的简单路径,输出这些路径上的宝藏珍惜度之和。
请注意,每一份宝藏只能被取一次。若某一条路径已经取走了 𝐴 处的宝藏,那么当另一条路径也经过 𝐴 处时,将无法再取。
这里的简单路径是指从起点出发,每一步都可以选择上下左右任意一个方向行走(前提是目标格可以通行),且路径上的每一个格子至多只经过一次,最终到达终点的路径。
输入描述:
第一行输入两个整数 𝑛 和 𝑚(2≤𝑛,𝑚≤1000) ,代表迷宫的长和宽。
此后 𝑛 行,每行输入 𝑚 个数字 𝑎1,𝑎2,…,𝑎𝑚 (−1≤𝑎𝑖≤109) ,表示迷宫中这一行的情况,其中 −1 表示该单元格无法通行。第一行第一个字符必定不为 −1 ,代表起点;最后一行最后一个字符必定不为 −1 ,代表终点。
输出描述:
在一行上输出一个整数,代表所有直达终点的路径上的宝藏数量。
示例1
输入
3 4
0 1 -1 9
0 -1 1 -1
0 0 0 0
输出
0
说明
如下图所示,只有唯一的路径可以直达终点,而这条路径上没有宝藏,所以答案为 0 。
##### 示例2
输入
4 4
0 1 0 3
0 -1 1 0
0 -1 -1 0
2 -1 0 0
输出
5
说明
如下图所示,一共有两条直达终点的路径,虽然两条路径都经过了第一行第二列的宝藏单元格,但每份宝藏只能被取一次,所以最终答案仍为 1+3+1=5。
题解
没想明白。难度很大啊,按照题解说法有俩做法。一个分治,看不懂;另一个就圆方图,看懂一般。
出题人题解:https://ac.nowcoder.com/acm/discuss/blogs?tagId=270832