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,fa,b,c,d,e,fa,b,c,d,e,f, 则向每次向左翻页时,新页面最左侧显示的题号为 min(1,a−6)min(1,a-6)min(1,a−6),同理每次向右翻页时,新页面最右侧显示的题号为min(n,f+6)min(n,f+6)min(n,f+6)
页面的最左侧可能出现多少不同的题号
思路
模拟一下会发现
如果题目数量 nnn ,能被 666 整除,
假设共 121212 页,只能向右翻页 222 次,依次为 1,2,3,4,5,61,2,3,4,5,61,2,3,4,5,6 和 7,8,9,10,11,127,8,9,10,11,127,8,9,10,11,12,
再向左翻回去,依次为 7,8,9,10,11,127,8,9,10,11,127,8,9,10,11,12 和 1,2,3,4,5,61,2,3,4,5,61,2,3,4,5,6,只有两种可能
答案也就是 n6\frac{n}{6}6n
如果题目数量 nnn ,不能被6整除,只有最后翻到底的时候,会出现翻页后得到的新页面存在和上一页重复的题号的情况
假设共 13 页,可以向右翻页 333 次,依次为1,2,3,4,5,61,2,3,4,5,61,2,3,4,5,6 和 7,8,9,10,11,127,8,9,10,11,127,8,9,10,11,12 还有 8,9,10,11,12,138,9,10,11,12,138,9,10,11,12,13,往回翻的过程中,每次翻页后所得新页面的最左侧的题目和翻过来的过程中不再重叠,依次为 8,9,10,11,12,138,9,10,11,12,138,9,10,11,12,13 和 2,3,4,5,6,72,3,4,5,6,72,3,4,5,6,7 还有 1,2,3,4,5,61,2,3,4,5,61,2,3,4,5,6
其他 n mod 6≠0n \bmod 6 \not= 0nmod6=0, 同理,答案为 2 * ⌊n6⌋\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 要有光
题意
如果绿幕高度不为 000
当点光源无限高时,所有区域都可以被照亮,逐渐降低点光源高度的过程中,逐渐出现未被点亮的区域,当点光源高度趋近于0时,未被点亮的面积趋于最大
当绿幕高度为 000 时,无遮挡,不会出现未被点亮的区域,即最大为 000。
思路

如果绿幕的高度不为 000 ,求梯形面积即可。
代码
/*******************************
| 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买外卖
题意
有 nnn 张可叠加的 满 xxx 减 yyy 元的优惠券, 本身手里有 mmm 元,问最多买多少钱的东西
思路
设第 i,ji,ji,j 张优惠券分别为 满 xix_ixi 减 yiy_iyi 元 和 满 xjx_jxj 减 yjy_jyj 元
如果 xi≤xjx_i \le x_jxi≤xj ,如果最后能用上满 xjx_jxj 减 yjy_jyj 元的优惠券,则 满 xix_ixi 减 yiy_iyi 元 的优惠券也可以被叠加使用,即变为 满 xjx_jxj 减 yj+yiy_j + y_iyj+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 按闹分配
题意
有一长度为 nnn 的数组 t,第 iii 个元素对应的不满意度 Di=∑i=1ntiD_i = \sum_{i=1}^nt_iDi=∑i=1nti ,
定义 S=∑i=1nDiS = \sum_{i=1}^nD_iS=∑i=1nDi,将一元素 xxx 插入数组 t 的第 iii 位,新的数组有 S′=∑i=1n+1DiS' = \sum_{i=1}^{n+1}D_iS′=∑i=1n+1Di 。
求满足 S′−S≤MS' - S \le MS′−S≤M 的 iii 的最小值。
思路
S′−S=(n−i)∗x+Di−1S' - S = (n-i)*x + D_{i-1}S′−S=(n−i)∗x+Di−1 ,求 iii 的最小值。
代码
/*******************************
| 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 本题又主要考察了贪心
题意
nnn 个选手,第 iii 名选手,目前得分为 aia_iai,接下来有 mmm 场比赛,胜者得 3 分,平局均得 1 分。
求在最好情况下,第 111 名选手的排名最高为多少。
思路
看数据范围,搜索所有可能性即可
代码
/*******************************
| 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;
}

1493

被折叠的 条评论
为什么被折叠?



