先附上补题链接,没打的同学可以来补一下:
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 k k 段字符串 , 每一个字符串 s i s_i si 的长度为 l i l_i li
对每一段字符串 s i s_i si ,里面任意一个连续子串都满足题意,因此需要计算出这个字符串里长度大于等于 2 2 2 的子串数量
可以理解为,对每一个字符可以看做开头,这个字符后面的任意字符看做结尾,那么这个字符串的符合题意子串数量为:
a n s = ∑ i = 1 k ( ( l i − 1 ) + ( l i − 2 ) ⋯ + 2 + 1 ) a n s = ∑ i = 1 k ( l i ∗ ( l i − 1 ) ÷ 2 ) ans = \sum_{i=1}^{k}{((l_i-1)+(l_i-2) \dots + 2 + 1)} \\ ans = \sum_{i=1}^{k}{(l_i * (l_i - 1) \div 2)} ans=i=1∑k((li−1)+(li−2)⋯+2+1)ans=i=1∑k(li∗(li−1)÷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 a a 个’0’、 b b b 个’1’ 让你组成一个01串,该01串有恰好 k k k 对相邻的字符不同。
做法
这是一道构造题,要求构造一个字符串满足题意
构造方法:
要构造 k k k 个相邻不同,使 01 交替排列形成长度为 k + 1 k+1 k+1 字符串即可
如果无法构造以上字符串,就输出 − 1 -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
x
x 能量,移动到当前位置右边、离当前位置最近的,和当前字符相同的字符;
2. 花费
y
y
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;
}
转载自博客https://www.cnblogs.com/jiejiejiang2004/p/18612596
博主已同意,我就是博主