A
签到
AC代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include <iostream> #include <queue> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <map> #include <vector> #include <set> #include <stack> #include <numeric> #include <iomanip> #define lowbit(x) ((x) & -(x)) using namespace std; const int INF = 0x3f3f3f3f; const int mod = 1000000007; void solve() { cout << "hello chino" << endl; return; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _t = 1; //cin >> _t; while (_t--) { solve(); } return 0; } /* */
B
分组背包,不选,选整个,选一半,转移方程dp[i][j]=dp[i-1][j]+dp[i-1][j-w[i]/2]+dp[i-1][j-w[i]]
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; const int mod = 1e9 + 7; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<vector<int>> dp(n + 1, vector<int> (m + 1)); vector<int> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; } dp[0][0] = 1; for (int i = 1; i <= n; i++) { for (int j = 0; j <= m; j++) { dp[i][j] = dp[i - 1][j] % mod; if (j >= a[i]) { dp[i][j] = (dp[i][j] + dp[i - 1][j - a[i]]) % mod; } if (j >= a[i] / 2) { dp[i][j] = (dp[i][j] + dp[i - 1][j - a[i] / 2]) % mod; } } } for (int i = 1; i <= m; i++) { cout << dp[n][i] << " \n"[i == m]; } return 0; }
C
该题为B题的逆过程,根据上一题的转移方程,我们可以稍微进行移向,dp[i][j]-dp[i-1][j-w[i]/2]-dp[i-1][j-w[i]]=dp[i-1][j],这样倒着递推就能得出答案,比如dp[1]=1,那他一定是一个重量为2的西瓜买了一半得到的方案
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; const int mod = 1e9 + 7; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int m, cnt = 0; cin >> m; vector<int> dp(m + 1); vector<int> ans(m + 1); dp[0] = 1; for (int i = 1; i <= m; i++) { cin >> dp[i]; } for (int i = 1; i <= m; i++) { while (dp[i]) { ans[cnt++] = 2 * i; for (int j = 0; i + j <= m; j++) { dp[i + j] = (dp[i + j] - dp[j] + mod) % mod; if (2 * i + j <= m) { dp[2 * i + j] = (dp[i * 2 + j] - dp[j] + mod) % mod; } } } } cout << cnt << '\n'; for (int i = 0; i < cnt; i++) { cout << ans[i] << " \n"[i == cnt - 1]; } return 0; }
D
签到,字符串
AC代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include <iostream> #include <queue> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <map> #include <vector> #include <set> #include <stack> #include <numeric> #include <iomanip> #define lowbit(x) ((x) & -(x)) using namespace std; const int INF = 0x3f3f3f3f; const int mod = 1000000007; void solve() { int n; cin >> n; string s; cin >> s; bool cnt1 = false,cnt0 = false; int x, y; for (int i = 0; i < n; i++) { if (s[i] == '0') { cnt0 = true; x = i; } else if (s[i] == '1') { y = i; cnt1 = true; } if (cnt1 && cnt0) { char op = s[y]; s[y] = s[x]; s[x] = op; break; } } cout << s << endl; return; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int _t = 1; //cin >> _t; while (_t--) { solve(); } return 0; } /* */
E
每次选取连续一段内所有相同颜色的数字,因为只能相同颜色之间的数字进行转换,所以贪心地考虑就是当遇到不同颜色或者字符串末尾,就把存储的相同颜色的数字进行从大到小排序,字符串转换成数字即可
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; const int mod = 1e9 + 7; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, k; cin >> n >> m >> k; string s; cin >> s; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } LL ans = 0; for (int i = 0; i < n;) { vector<int> z; int j = i; while (a[i] == a[j] && j < n) { z.push_back(s[j] - '0'); j++; } sort(z.begin(), z.end(), greater<int> ()); for (auto it : z) { ans = (ans * 10 + it) % mod; } i = j; } cout << ans << '\n'; ans = 0; while (k--) { int p, q; cin >> p >> q; for (int i = 0; i < n; i++) { if (a[i] == p) { a[i] = q; } } for (int i = 0; i < n;) { vector<int> z; int j = i; while (a[i] == a[j] && j < n) { z.push_back(s[j] - '0'); j++; } sort(z.begin(), z.end(), greater<int> ()); for (auto it : z) { ans = (ans * 10 + it) % mod; } i = j; } cout << ans << '\n'; ans = 0; } return 0; }
I
二分或者尺取
二分和尺取共同思路是先把每种类型的字符都数字化
尺取先找到符合的区间,再根据区间右边界确定左边界取到哪里
二分在符合条件的区间内二分确定[l,r]边界
AC代码:
尺取:
/*########################################################## # File Name: 3.cpp # Author: HideInTheSea # Created Time: 2022年11月21日 星期一 21时05分39秒 ##########################################################*/ #include <bits/stdc++.h> using namespace std; using LL = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, l, r; cin >> n >> l >> r; string s; cin >> s; s = '#' + s; vector<int> a(n + 1); vector<int> cnt(5, 0); for (int i = 1; i <= n; i++) { if (s[i] >= 'A' and s[i] <= 'Z') { a[i] = 1; } else if (s[i] >= 'a' and s[i] <= 'z') { a[i] = 2; } else if (s[i] >= '0' and s[i] <='9') { a[i] = 3; } else { a[i] = 4; } } LL ans = 0; for (int i = 1, j = 0; i <= n; i++) { while (j < n + 1 and ((cnt[1] > 0) + (cnt[2] > 0) + (cnt[3] > 0) + (cnt[4] > 0)) < 3) { if (j < n) { cnt[a[j + 1]]++; } j++; } int L = max(j, i + l - 1); int R = min(n, i + r - 1); ans += max(0, R - L + 1); cnt[a[i]]--; } cout << ans << '\n'; return 0; }
二分:
/*########################################################## # File Name: 2.cpp # Author: HideInTheSea # Created Time: 2022年11月21日 星期一 19时42分42秒 ##########################################################*/ #include <bits/stdc++.h> using namespace std; using LL = long long; #define int long long signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, l, r; cin >> n >> l >> r; string s; cin >> s; s = '#' + s; vector<vector<LL>> dp(n + 1, vector<LL> (5)); vector<int> a(n + 1); for (int i = 1; i <= n; i++) { if (s[i] >= 'A' and s[i] <= 'Z') { a[i] = 1; } else if (s[i] >= 'a' and s[i] <= 'z') { a[i] = 2; } else if (s[i] >= '0' and s[i] <= '9') { a[i] = 3; } else { a[i] = 4; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= 4; j++) { dp[i][j] = dp[i - 1][j] + (a[i] == j); } } LL ans = 0; function<bool(int, int)> check = [&](int x, int y) { int k = (dp[y][1] - dp[x - 1][1] > 0 ? 1 : 0) + (dp[y][2] - dp[x - 1][2] > 0 ? 1 : 0) + (dp[y][3] - dp[x - 1][3] > 0 ? 1 : 0) + (dp[y][4] - dp[x - 1][4] > 0 ? 1 : 0); if (k >= 3) { return true; } else { return false; } }; for(int i = 1; i <= n - l + 1; i++){ int R = min(i + r - 1, n); int L = i; if(check(L, R)){ while(L < R){ int mid = (L + R) >> 1; if(check(i, mid)) R = mid; else L = mid + 1; } L = max(L, i + l - 1); ans += min(i + r - 1, n) - L + 1; } } cout << ans << '\n'; return 0; }
L
读懂题意,模拟
AC代码:
/*########################################################## # File Name: 1.cpp # Author: HideInTheSea # Created Time: 2022年11月21日 星期一 18时54分05秒 ##########################################################*/ #include <bits/stdc++.h> using namespace std; using LL = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<string> s(m + 1); vector<vector<int>> a(n + 1, vector<int> (m + 1)); for (int i = 1; i <= m; i++) { cin >> s[i]; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; } } string q; while (cin >> q) { if (q == "BY") { cin >> q; break; } } int len = q.size(); vector<bool> vis(m + 1); bool ok = false; for (int i = 0; i < len;) { string z = ""; while (i != len and q[i] != ',' and q[i] != ';') { z += q[i]; i++; } for (int i = 1; i <= m; i++) { if (z == s[i]) { vis[i] = true; break; } } i++; if (q[i] == ';') { break; } } map<vector<int>, int> mp; for (int i = 1; i <= n; i++) { vector<int> qu; for (int j = 1; j <= m; j++) { if (vis[j]) { qu.push_back(a[i][j]); } } mp[qu]++; } cout << mp.size() << '\n'; for (auto it : mp) { cout << it.second << " "; } cout << '\n'; return 0; }
2022牛客寒假算法基础集训营3(7/12)
于 2022-02-15 14:31:22 首次发布