jiejiejiang2004

题解:牛客周赛 Round 72(A-D)(E只有代码)

先附上补题链接,没打的同学可以来补一下:

https://ac.nowcoder.com/acm/contest/98256


A 小红的01串(一)

题意

找到一个01串中相邻字符不同的对数

做法

从头到尾扫一遍,计算前后不一样的字符就可以了

#include <bits/stdc++.h>
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::string s;
std::cin >> s;
int ans = 0;
for(int i = 0 ; i + 1 < s.size() ; i ++) {
ans += (s[i] != s[i+1]);
}
std::cout << ans << "\n";
return 0;
}

B 小红的01串(二)

题意

给你一个01串,输出相邻字符均不同的连续子串数量

做法

这题就是直接扫一遍,找到每一段 尽可能长的 相邻字符均不同 的字符串(不要重复)

写个双指针就好了

设共有 k 段字符串 , 每一个字符串 si 的长度为 li

对每一段字符串 si ,里面任意一个连续子串都满足题意,因此需要计算出这个字符串里长度大于等于 2 的子串数量

可以理解为,对每一个字符可以看做开头,这个字符后面的任意字符看做结尾,那么这个字符串的符合题意子串数量为:

ans=i=1k((li1)+(li2)+2+1)ans=i=1k(li(li1)÷2)

#include <bits/stdc++.h>
#define int long long
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::string s;
std::cin >> s;
int ans = 0;
int sum = 0;
for(int i = 0 ; i < s.size() - 1; i ++) {
if(s[i] != s[i+1]) sum ++;
else if(sum) {
ans += sum * (sum+1) / 2;
sum = 0;
}
}
if(sum) ans += sum * (sum+1) / 2;
std::cout << ans << "\n";
return 0;
}

C 小红的01串(三)

题意

给你 a 个'0'、b 个'1' 让你组成一个01串,该01串有恰好 k 对相邻的字符不同。

做法

这是一道构造题,要求构造一个字符串满足题意

构造方法:

要构造 k 个相邻不同,使 01 交替排列形成长度为 k+1 字符串即可

如果无法构造以上字符串,就输出 1

然后再把剩下的 0 和 1 塞到中间即可

注意特判 k = 0 或者 a = 0, b = 0

#include <bits/stdc++.h>
#define int long long
void solve() {
int a,b,k;
std::cin >> a >> b >> k;
if(k == 0 && a > 0 && b > 0) {
std::cout << -1 << "\n";
return;
}
if(k == 0 && (a == 0 || b == 0)) {
while(a--) std::cout << 0;
while(b--) std::cout << 1;
std::cout << "\n";
return;
}
if(k != 0 && (a == 0 || b == 0)) {
std::cout << -1 << "\n";
return;
}
int mp[2] = {0,1};
if(a > b) {
std::swap(a,b);
std::swap(mp[0],mp[1]);
}
if(a < (k+1)/2 || b < (k+2)/2) {
std::cout << "-1" << "\n";
return;
}
int last_a = a - (k+1)/2;
int last_b = b - (k+2)/2;
std::cout << mp[1];
while(last_b --) std::cout << mp[1];
std::cout << mp[0];
while(last_a --) std::cout << mp[0];
for(int i = 2 ; i <= k ; i ++) {
std::cout << mp[(i+1)%2];
}
std::cout << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int t = 1;
std::cin >> t;
while(t--) {
solve();
}
return 0;
}

D 小红的01串(四)

题意

小红拿到了一个01串,她初始站在第一个字符。小红可以进行以下移动方式:
1. 花费 x 能量,移动到当前位置右边、离当前位置最近的,和当前字符相同的字符;
2. 花费 y 能量,移动到当前位置右边、离当前位置最近的,和当前字符不同的字符。

小红想知道,她移动到最右端的最小花费是多少?

做法

dp 一下就好了

先从后往前扫一遍,找到每一个的下一个(一样的 和 不一样的)点 在哪里

然后再初始化dp数组为最大值,dp[0] = 0;

然后从前往后开始dp,更新每一个的下一个(一样的 和 不一样的)点的dp值(尽可能小)

然后输出最后一个的dp值即可

#include <bits/stdc++.h>
#define int long long
#define INF (int)1e18
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n,x,y;
std::string s;
std::cin >> n >> x >> y >> s;
std::vector<int> dp(n,INF);
std::vector<std::vector<int> > next(n,std::vector<int>(2,-1));
int two[2] = {INF,INF};
for(int i = n-1 ; i >= 0 ; i --) {
next[i][0] = (two[s[i] - '0'] == INF ? -1 : two[s[i] - '0']);
next[i][1] = (two[1 - (s[i] - '0')] == INF ? -1 : two[1 - (s[i] - '0')]);
two[s[i] - '0'] = i;
}
dp[0] = 0;
for(int i = 0 ; i < n ; i ++) {
if(next[i][0] != -1) {
dp[next[i][0]] = std::min(dp[next[i][0]] , dp[i] + x);
}
if(next[i][1] != -1) {
dp[next[i][1]] = std::min(dp[next[i][1]] , dp[i] + y);
}
}
std::cout << dp[n-1] << "\n";
return 0;
}

E 小红的01串(五)

这题也是dp

具体思路我不知道怎么表述(我也是补题的)

直接看代码吧

#include <bits/stdc++.h>
#define int long long
#define all(x) x.begin(),x.end()
const int mod = 1e9 + 7;
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::string s;
std::cin >> s;
std::reverse(all(s));
int n = s.size();
s = " " + s;
std::vector<std::vector<int> > dp(n+1,std::vector<int>(13,0));
dp[0][0] = 1;
int tot = 1;
for(int i = 1 ; i <= n ; i ++) {
if(s[i] == '?') {
for(int j = 0 ; j < 13 ; j ++) {
dp[i][j] += dp[i-1][j];
dp[i][j] %= mod;
dp[i][(j + tot)%13] += dp[i-1][j];
dp[i][(j + tot)%13] %= mod;
}
} else {
if(s[i] == '0') {
for(int j = 0 ; j < 13 ; j ++) {
dp[i][j] += dp[i-1][j];
dp[i][j] %= mod;
}
} else {
for(int j = 0 ; j < 13 ; j ++) {
dp[i][(j + tot)%13] += dp[i-1][j];
dp[i][(j + tot)%13] %= mod;
}
}
}
tot *= 10;
tot %= 13;
}
std::cout << dp[n][0] << "\n";
return 0;
}

posted on   Jiejiejiang  阅读(29)  评论(0编辑  收藏  举报

编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」

导航

统计信息

点击右上角即可分享
微信分享提示