2024牛客寒假算法基础集训营1 题解
A DFS搜索
题意
找所给字符串中是否有依次出现的 ‘D’ ‘F’ ‘S’ 和 ‘d’ ‘f’ ‘s’
思路
所以可以依次判断两种情况
- 找到D再找F再找S
- 找到d再找f再找s
依次根据是否满足条件输出1或0
代码
/*******************************
| Author: AlwaysBeShine
| Problem: DFS搜索
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/A
| When: 2024-02-02 13:00:53
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n;
cin >> n;
string s;
cin >> s;
int cnt1 = 0,cnt2 = 0;
for(int i = 0;i < n;i++){
if(s[i] == 'D' && cnt1 == 0){
cnt1 = 1;
}else if(s[i] == 'F' && cnt1 == 1){
cnt1 = 2;
}else if(s[i] == 'S' && cnt1 == 2){
cnt1 = 3;
}
if(s[i] == 'd' && cnt2 == 0){
cnt2 = 1;
}else if(s[i] == 'f' && cnt2 == 1){
cnt2 = 2;
}else if(s[i] == 's' && cnt2 == 2){
cnt2 = 3;
}
}
if(cnt1 == 3){
cout << 1 << " ";
}else{
cout << 0 << " ";
}
if(cnt2 == 3){
cout << 1 << endl;
}else{
cout << 0 << endl;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
M 牛客老粉才知道的秘密
题意
屏幕固定一次性显示6题(例如1 2 3 4 5 6),共有 n 道题,若当前所显示的6道题的题号依次为 a , b , c , d , e , f a,b,c,d,e,f a,b,c,d,e,f, 则向每次向左翻页时,新页面最左侧显示的题号为 m i n ( 1 , a − 6 ) min(1,a-6) min(1,a−6),同理每次向右翻页时,新页面最右侧显示的题号为 m i n ( n , f + 6 ) min(n,f+6) min(n,f+6)
页面的最左侧可能出现多少不同的题号
思路
模拟一下会发现
如果题目数量
n
n
n ,能被
6
6
6 整除,
假设共
12
12
12 页,只能向右翻页
2
2
2 次,依次为
1
,
2
,
3
,
4
,
5
,
6
1,2,3,4,5,6
1,2,3,4,5,6 和
7
,
8
,
9
,
10
,
11
,
12
7,8,9,10,11,12
7,8,9,10,11,12,
再向左翻回去,依次为
7
,
8
,
9
,
10
,
11
,
12
7,8,9,10,11,12
7,8,9,10,11,12 和
1
,
2
,
3
,
4
,
5
,
6
1,2,3,4,5,6
1,2,3,4,5,6,只有两种可能
答案也就是
n
6
\frac{n}{6}
6n
如果题目数量
n
n
n ,不能被6整除,只有最后翻到底的时候,会出现翻页后得到的新页面存在和上一页重复的题号的情况
假设共 13 页,可以向右翻页
3
3
3 次,依次为
1
,
2
,
3
,
4
,
5
,
6
1,2,3,4,5,6
1,2,3,4,5,6 和
7
,
8
,
9
,
10
,
11
,
12
7,8,9,10,11,12
7,8,9,10,11,12 还有
8
,
9
,
10
,
11
,
12
,
13
8,9,10,11,12,13
8,9,10,11,12,13,往回翻的过程中,每次翻页后所得新页面的最左侧的题目和翻过来的过程中不再重叠,依次为
8
,
9
,
10
,
11
,
12
,
13
8,9,10,11,12,13
8,9,10,11,12,13 和
2
,
3
,
4
,
5
,
6
,
7
2,3,4,5,6,7
2,3,4,5,6,7 还有
1
,
2
,
3
,
4
,
5
,
6
1,2,3,4,5,6
1,2,3,4,5,6
其他
n
m
o
d
6
≠
0
n \bmod 6 \not= 0
nmod6=0, 同理,答案为 2 *
⌊
n
6
⌋
\lfloor \frac{n}{6} \rfloor
⌊6n⌋
代码
/*******************************
| Author: AlwaysBeShine
| Problem: 牛客老粉才知道的秘密
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/M
| When: 2024-02-02 13:42:46
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
ll n;
cin >> n;
ll ans = 0;
ans += n / 6;
if(n % 6 != 0)ans += n / 6;
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
L 要有光
题意
如果绿幕高度不为 0 0 0
当点光源无限高时,所有区域都可以被照亮,逐渐降低点光源高度的过程中,逐渐出现未被点亮的区域,当点光源高度趋近于0时,未被点亮的面积趋于最大
当绿幕高度为 0 0 0 时,无遮挡,不会出现未被点亮的区域,即最大为 0 0 0。
思路
如果绿幕的高度不为 0 0 0 ,求梯形面积即可。
代码
/*******************************
| Author: AlwaysBeShine
| Problem: 要有光
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/L
| When: 2024-02-02 16:04:57
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
double c,d,h,w;
cin >> c >> d >> h >> w;
if(h <= 0){
cout << fixed << setprecision(8) << 0.00000000 << endl;
}else{
double ans = 3*w *c;
cout << fixed << setprecision(8) << ans << endl;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
G why买外卖
题意
有 n n n 张可叠加的 满 x x x 减 y y y 元的优惠券, 本身手里有 m m m 元,问最多买多少钱的东西
思路
设第
i
,
j
i,j
i,j 张优惠券分别为 满
x
i
x_i
xi 减
y
i
y_i
yi 元 和 满
x
j
x_j
xj 减
y
j
y_j
yj 元
如果
x
i
≤
x
j
x_i \le x_j
xi≤xj ,如果最后能用上满
x
j
x_j
xj 减
y
j
y_j
yj 元的优惠券,则 满
x
i
x_i
xi 减
y
i
y_i
yi 元 的优惠券也可以被叠加使用,即变为 满
x
j
x_j
xj 减
y
j
+
y
i
y_j + y_i
yj+yi 元。
如何实现叠加过程?
当出现以上情况时,则将低满减额的折扣额加给高满减额的折扣额
叠加完毕后,判断
如何判断是否可以使用呢?
当 原价
≤
\le
≤ 满减额 时,原价 - 优惠券折扣额
≤
\le
≤ m 即可使用
即求 当 满减额 - 折扣额
≤
\le
≤ m 时的 m - 折扣额 的最大值。
代码
/*******************************
| Author: AlwaysBeShine
| Problem: why买外卖
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/G
| When: 2024-02-02 14:53:04
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
ll n,m;
cin >> n >> m;
vector<pair<ll,ll>> q;
map<ll,int>pos;
for(int i = 0;i < n;i++){
ll a,b;
cin >> a >> b;
if(pos[a] == 0){
q.push_back({a,b});
pos[a] = q.size() - 1;
}else{
q[pos[a]].second += b;
}
}
sort(q.begin(),q.end());
for(int i = 0;i < q.size()-1;i++){
q[i+1].second += q[i].second;
}
ll res = -1;
for(int i = q.size()-1;i >= 0;i--){
if(q[i].first - q[i].second <= m)
res = max(q[i].first+m-(q[i].first-q[i].second),res);
}
if(res == -1){
cout << m << endl;
}else{
cout << res << endl;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
C 按闹分配
题意
有一长度为
n
n
n 的数组 t,第
i
i
i 个元素对应的不满意度
D
i
=
∑
i
=
1
n
t
i
D_i = \sum_{i=1}^nt_i
Di=∑i=1nti ,
定义
S
=
∑
i
=
1
n
D
i
S = \sum_{i=1}^nD_i
S=∑i=1nDi,将一元素
x
x
x 插入数组 t 的第
i
i
i 位,新的数组有
S
′
=
∑
i
=
1
n
+
1
D
i
S' = \sum_{i=1}^{n+1}D_i
S′=∑i=1n+1Di 。
求满足
S
′
−
S
≤
M
S' - S \le M
S′−S≤M 的
i
i
i 的最小值。
思路
S ′ − S = ( n − i ) ∗ x + D i − 1 S' - S = (n-i)*x + D_{i-1} S′−S=(n−i)∗x+Di−1 ,求 i i i 的最小值。
代码
/*******************************
| Author: AlwaysBeShine
| Problem: 按闹分配
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/C
| When: 2024-02-02 16:59:05
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll n,Q,T,ans;
cin >> n >> Q >> T;
vector<ll>t(n+1,0);
for(int i = 1;i <= n;i++){
cin >> t[i];
}
sort(t.begin(),t.end());
ll sum_min = 0;
for(int i = 1;i <= n;i++){
t[i] += t[i-1];
sum_min += t[i];
}
while(Q--){
ll M;
cin >> M;
ll cnt = M / T;
if(M >= n*T){
cout << T << endl;
}else{
cout << t[n-cnt] + T << endl;
}
}
return 0;
}
E 本题又主要考察了贪心
题意
n n n 个选手,第 i i i 名选手,目前得分为 a i a_i ai,接下来有 m m m 场比赛,胜者得 3 分,平局均得 1 分。
求在最好情况下,第 1 1 1 名选手的排名最高为多少。
思路
看数据范围,搜索所有可能性即可
代码
/*******************************
| Author: AlwaysBeShine
| Problem: 本题又主要考察了贪心
| Contest: NowCoder
| URL: https://ac.nowcoder.com/acm/contest/67741/E
| When: 2024-02-05 23:26:34
|
| Memory: 524288 MB
| Time: 2000 ms
*******************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// 0 输 1赢 2 平
int n,m,a[11],u[11],v[11];
int bt = 100;
void dfs(int round,int A[],int U[],int V[]){
if(round == m+1){
int cnt = 1;
for(int i = 2;i <= n;i++){
if(A[i] > A[1])cnt++;
}
bt = min(bt,cnt);
return;
}else{
A[U[round]] += 3;
dfs(round+1,A,U,V);
A[U[round]] -= 3;
A[V[round]] += 3;
dfs(round+1,A,U,V);
A[V[round]] -= 3;
A[V[round]]++;
A[U[round]]++;
dfs(round+1,A,U,V);
A[V[round]]--;
A[U[round]]--;
}
}
void solve(){
bt = 100;
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> a[i];
}
for(int i = 1;i <= m;i++){
cin >> u[i] >> v[i];
}
dfs(1,a,u,v);
cout << bt << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}