牛客周赛 Round 54
A - 清楚姐姐的糖葫芦
题意
数给定字符串中的o的个数
代码
#include <bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int main()
{
string s;
cin>>s;
int cnt=0;
for(char c:s)
{
if(c=='o')
cnt++;
}
printf("%d\n",cnt);
return 0;
}
B - 清楚姐姐买竹鼠
题意
一只竹鼠a元,三只竹鼠b元,问买x只竹鼠最少花多少钱
思路
首先判断单买三只的价格是否比b小,如果单买更划算就全部单买
不然的话就尽量三只三只买,然后再把剩下的单只单只买,这很好想到,但到这里你会发现只有90分,WA了一个点,还好这是IOI赛制,不用慌
如果买三只的价格特别低,那我其实可以再最后要买一只或者两只的时候多买几只凑三只买,当然也可以比较单买两只和三只的价格,但是我就直接写了个取最小值了
代码
#include <bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int main()
{
ll a,b,x;
cin>>a>>b>>x;
ll ans=0;
if(a*3<=b)
ans=a*x;
else
ans=min((x/3)*b+(x%3)*a,b*(x/3+(x%3==0?0:1)));
printf("%lld\n",ans);
return 0;
}
C - 竹鼠饲养物语
题面
\,\,\,\,\,\,\,\,\,\, 鼠鼠快速成长饲料一共分为 m m m 个等级,初始时全部竹鼠都是零级竹鼠,投喂一袋“鼠鼠快速成长饲料 I \rm I I ”可以升级为一级竹鼠,继续投喂“鼠鼠快速成长饲料 I I \rm II II ”可以升级为二级竹鼠,……。需要注意的是,你不能越级投喂,例如,向零级竹鼠投喂“鼠鼠快速成长饲料 I I \rm II II ”没有任何效果。
\,\,\,\,\,\,\,\,\,\, 清楚一共有 n n n 袋饲料和无限多的零级竹鼠,问最多可以进行多少次有效投喂。
思路
很容易想到开桶记录每一个等级的饲料有多少,然后后面比前面多的话多出来的就不算,但是被1e9的范围吓唬回去了。但是仔细想一下,最多1e5袋,就算是最坏的情况也顶多升1e5级,后面等级的饲料其实我都不需要考虑,所以桶只需要开1e5就可以了
代码
#include <bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
ll st[100005];
ll ans=0;
memset(st,0,sizeof(st));
for(int i=1;i<=n;i++)
{
ll x;
scanf("%lld",&x);
if(x<=100005)
st[x]++;
}
for(int i=2;i<=min(m,100005ll);i++)
{
if(st[i]>st[i-1])
st[i]=st[i-1];
}
for(int l=1;l<=min(m,100005ll);l++)
{
if(st[l]==0)
break;
ans+=st[l];
}
printf("%lld\n",ans);
return 0;
}
D - 清楚姐姐跳格子
题面
\,\,\,\,\,\,\,\,\,\, 清楚正在玩跳格子游戏。地上有 n n n 个格子,清楚一开始在 1 1 1 号格子,目标是 n n n 号格子。
\,\,\,\,\,\,\,\,\,\, 第 i i i 个格子上有一个数字 a i a_i ai ,清楚在这个格子上可以往左右两边选一个方向,然后选择 a i a_i ai 的一个正整数因子作为长度,进行一次跳跃,但是不可以跳出边界。
\,\,\,\,\,\,\,\,\,\, 请问清楚最少跳多少步,就可以到达 n n n 号格子。
思路
一开始想的肯定是dfs,但是因数太多,一个点可以跳去好几个不同的位置,但是又只有1000个点,那么我们自然的就可以想到建邻接表,对每一个可以走的位置建有向边跑dijkstra,但是现在因数太多又是个问题。我们求一个数所有因数最快也需要 O ( n ) O(\sqrt{n}) O(n),这里的a的数据范围又是1e18,肯定是不行的。但是有了上一题的经验,我们再仔细看一下,其实每个点我们只需要找1000内的因数就可以了,所以一样可以正常解决
代码
#include <bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
vector<int> G[1005];
int main()
{
int n;
scanf("%d",&n);
vector<ll> a(n+1);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
int b=max(abs(n-i),abs(i-1));
for(int j=1;j<=b;j++)
{
if(a[i]%j==0)
{
if(i+j<=n)
G[i].push_back(i+j);
if(i-j>=1)
G[i].push_back(i-j);
}
}
}
ll ans=0;
//dijkstra求1到n的最短路 以G[i]为邻接表
vector<ll> dis(n+1,1e18);
dis[1]=0;
priority_queue<pll,vector<pll>,greater<pll>> q;
q.push({0,1});
while(!q.empty())
{
pll p=q.top();
q.pop();
int u=p.second;
if(p.first>dis[u])
continue;
for(int v:G[u])
{
if(dis[v]>dis[u]+1)
{
dis[v]=dis[u]+1;
q.push({dis[v],v});
}
}
}
ans=dis[n];
printf("%lld\n",ans);
return 0;
}