今天血崩,基本没有独立写完的 orz,太菜了还是要要多练练。
P8649 [蓝桥杯 2017 省 B] k 倍区间
一开始就暴力前缀和,结果果然没有全部拿下,剪了一会枝结果并没有什么卵用 orz。出去逛了一圈题解学到了同余的思想,wr 我怎么想不到捏,还是挺好理解的。就是说差是 K 的倍数的两个数,对 K 取余的余数是一致的。然后注意余数为 0 的天然有一个,代码:
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; ll a[100010], cnt[100010]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); mem(a, 0); mem(cnt, 0); cnt[0]++; int n, k; ll ans = 0; cin >> n >> k; for(int i = 1; i <= n; i++){ cin >> ans; a[i] = a[i - 1] + ans; a[i] %= k; cnt[a[i]]++; } ans = 0; for(int i = 0; i < k; i++){ ans += (cnt[i] * (cnt[i] - 1)) / 2; } cout << ans << endl; return 0; }
P8697 [蓝桥杯 2019 国 C] 最长子序列
这题第一反应是用 DP,看了一眼标签果然是 DP,推了半天推不出递推式 orz,再逛一圈看到有说用双指针,尝试写了一下,果然通过了。。。。
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; string t, s; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; cin >> s; int m = t.size(), n = s.size(); int i = 0, j = 0, ans = 0; while(i < m && j < n){ if(t[i] == s[j]){ ans++, i++, j++; }else{ i++; } } cout << ans << endl; return 0; }
P1043 [NOIP2003 普及组] 数字游戏
绿题对于我来说果然还是太难了,看了半天题解才写出来,用两个数组记录状态,B(S)[i][j][l]表示从 i 到 j 分割成 l 部分的最大(小)值。注意取余的特殊操作和段环为链的操作,然后依次枚举开头点截止点,部分数和前 l-1 部分与第 l 部分的分界点来进行状态转移。注意要初始化,emmm
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; ll a[101], b[101][101][10], s[101][101][10]; int mod(int x){ return ((x % 10) + 10) % 10; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); mem(b, 0); mem(s, 1); int n, m; cin >> n >> m; for(int i = 1; i <= n; i++){ cin >> a[i]; a[i + n] = a[i]; } for(int i = 1; i <= 2 * n; i++){ a[i] += a[i - 1]; } for(int i = 1; i <= 2 * n; i++){ for(int j = 1; j <= 2 * n; j++){ b[i][j][1] = mod(a[j] - a[i - 1]); s[i][j][1] = mod(a[j] - a[i - 1]); } } for(int i = 1; i <= 2 * n; i++){ for(int j = i + 1; j <= 2 * n; j++){ for(int l = 2; l <= m; l++){ for(int k = i; k < j; k++){ b[i][j][l] = max(b[i][j][l], b[i][k][l - 1] * b[k + 1][j][1]); s[i][j][l] = min(s[i][j][l], s[i][k][l - 1] * s[k + 1][j][1]); } } } } ll maxl = 0, minl; mem(&minl, 1); for(int i = 1; i <= n; i++){ maxl = max(maxl, b[i][i + n - 1][m]); minl = min(minl, s[i][i + n - 1][m]); } cout << minl << endl << maxl << endl; return 0; }