2025年3月CSP,回顾 + 题解。
回顾 得分 100 - 100 - 80 - 100 - 15
。
T1 T2大概花了 15min,T4 大概 30min 过掉,剩下时间都在写 T3, T5。
本场败笔在 T3,在 DAG 上 DFS 暴搜,没写记忆化,只拿了 80 分。卡在 395,与 400 失之交臂了(哭
T5 Link Cut Tree,神秘的高级数据结构,暂时不补。
题解 数值积分 按题意模拟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> #define int long long using namespace std;void solve () { int b, c, l, r; cin >> b >> c >> l >> r; if (l & 1 ) l++; if (r & 1 ) r--; int res = 0 ; for (int i = l; i <= r; i += 2 ){ res += 2 * (i * i + b * i + c); } cout << res << '\n' ; } signed main () { ios::sync_with_stdio (0 ); cin.tie (0 ); solve (); return 0 ; }
机器人饲养指南 $$ \sum i = n\ \ \Rightarrow\ \ \max(\sum a_i) $$
记 $dp[i]$ 为投喂 $i$ 个时的最大快乐值,转移为: $$ dp[i]=\max_{i-m\le j<i}(dp[j]+a[i-j]) $$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> #define int long long using namespace std;void solve () { int n, m; cin >> n >> m; vector<int > a (m + 1 ) ; for (int i = 1 ; i <= m; i++) cin >> a[i]; vector<int > dp (n + 1 ) ; for (int i = 1 ; i <= n; i++){ for (int j = max (0ll , i - m); j < i; j++){ dp[i] = max (dp[i], dp[j] + a[i - j]); } } cout << dp[n] << '\n' ; } signed main () { ios::sync_with_stdio (0 ); cin.tie (0 ); solve (); return 0 ; }
模板展开 理解题意:
那么抽象出来就是一张 DAG,每次修改点权或点权与出边,求值。
对每次 query,做一个记忆化,避免重复搜索。
同时学习一下 istringstream 字符串输入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 #include <bits/stdc++.h> using namespace std;constexpr int mod = 1e9 + 7 ;unordered_map<string, int > StoI; vector<int > val (1005 ) ;vector<vector<int >> adj (1005 ); unordered_map<int , int > mp; int idx = 1 ;inline int get_idx (string s) { if (StoI[s]) return StoI[s]; return StoI[s] = idx++; } inline int getlen (int x) { if (mp[x]) return mp[x]; int res = val[x]; for (auto &i : adj[x]){ res += getlen (i); res %= mod; } return mp[x] = res % mod; } void solve () { int q; cin >> q; cin.ignore (); while (q--){ string line; getline (cin, line); istringstream iss (line) ; string op; iss >> op; string tmpvar; iss >> tmpvar; vector<string> expr; string ex; while (iss >> ex) expr.emplace_back (ex); int var = get_idx (tmpvar); if (op == "1" ){ int sum = 0 ; for (auto &s : expr){ if (s[0 ] != '$' ){ sum += s.size (); sum %= mod; } else { int ss = get_idx (s.substr (1 , s.size () - 1 )); sum += getlen (ss); sum %= mod; } } val[var] = sum; adj[var].clear (); } else if (op == "2" ){ adj[var].clear (); int sum = 0 ; for (auto &s : expr){ if (s[0 ] != '$' ){ sum += s.size (); sum %= mod; } else { int ss = get_idx (s.substr (1 , s.size () - 1 )); adj[var].emplace_back (ss); } } val[var] = sum; } else { cout << getlen (var) << '\n' ; } mp.clear (); } } signed main () { ios::sync_with_stdio (0 ); cin.tie (0 ); solve (); return 0 ; }
集体锻炼 观察到,固定右端点 $r$ 时,区间 $[l, r]$ 的 gcd 可能取值数不超过 $log(r-l+1)$。
因此维护每一段 gcd 不同的区间,每加入一个右端点,更新一遍区间,合并相同区间,逐个区间地去计算贡献。
时间复杂度 $O(n\log n)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <bits/stdc++.h> #define int long long using namespace std;constexpr int mod = 998244353 ;int gcd (int a, int b) { return b ? gcd (b, a % b) : a; } struct split { int r, g; split (int r, int g) : r (r), g (g) {} }; void solve () { int n; cin >> n; vector<int >a (n + 1 ); for (int i = 1 ; i <= n; i++) cin >> a[i]; vector<split>S; int res = 0 ; for (int i = 1 ; i <= n; i++){ vector<split>tmp; S.emplace_back (i, a[i]); for (int j = 0 ; j < S.size (); j++){ S[j].g = gcd (S[j].g, a[i]); if (tmp.empty ()){ tmp.push_back (S[j]); } else if (S[j].g == tmp.back ().g){ tmp.back ().r = S[j].r; } else { tmp.push_back (S[j]); } } S.swap (tmp); int sum = S[0 ].r * (S[0 ].r + 1 ) / 2 * S[0 ].g % mod; for (int i = 1 ; i < S.size (); i++){ sum += (S[i].r * (S[i].r + 1 ) / 2 - S[i - 1 ].r * (S[i - 1 ].r + 1 ) / 2 ) % mod * S[i].g % mod; sum %= mod; } res += sum * i; res %= mod; } cout << res << '\n' ; } signed main () { ios::sync_with_stdio (0 ); cin.tie (0 ); solve (); return 0 ; }
成绩