Codeforces Round #833 (Div. 2)
A. The Ultimate Square (CF 1748 A)
题目大意
给定块板,第块板的宽为 ,长为 。问用这些板可以组成一个正方形,问其最大的边长是多少。
解题思路
题意可以相当于给定了长度为板各两个。
当 是奇数时,第一块板和第 块板组合,第二块板和第块板组合,刚好组成 块长度为板,加上第 块板刚好可以组成长度为 的正方形
当是偶数时直接前后组合,也同样可以组成长度为的正方形。
因此答案就是
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int x; cin >> x; cout << (x + 1) / 2 << '\n'; } return 0; }
B. Diverse Substrings (CF 1748 B)
题目大意
给定一个仅包含数字的字符串,问其有多少个子串,记表示数字 的出现次数, 为不同数字的个数,满足所有数字 均有
解题思路
注意数字种类只有个,因此合法串的长度最长也就 ,因此对长度为 的所有子串暴力 判断即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n; cin >> n; string s; cin >> s; LL ans = 0; for(int i = 0; i < s.size(); ++ i){ map<int, int> qwq; set<int> ff; auto check = [&](){ for(auto &i : qwq) if (i.second > ff.size()) return false; return true; }; for(int j = 1; j <= 100; ++ j){ int r = i + j - 1; if (r >= s.size()) break; ff.insert(s[r]); qwq[s[r]] ++; if (check()) ++ ans; } } cout << ans << '\n'; } return 0; }
C. Zero-Sum Prefixes (CF 1748 C)
题目大意
给定一个长度为的整数组 ,可以将其中为的项变为任意数字,问其前缀和为的最大数量是多少,即最大化满足以下条件的的数量,使得 。
解题思路
即前缀和
从左到右考虑每个,假设当前考虑的下标是 ,其值为, 下一个的下标为。考虑对前者的更改其值,将影响的值,即这些值中出现次数最多的是 ,很显然我们将 变成 ,这样就尽可能有更多的前缀和为 ,同时也不影响 (该相同的还是相同)。
因此统计每两个相邻之间前缀和出现最多的次数即可。注意别忘了第一个出现前前缀和为的数量。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ int n; cin >> n; vector<int> a(n); for(auto &i : a) cin >> i; bool zero = false; map<LL, LL> cnt; LL ans = 0; LL sum = 0; for(int i = 0; i < n; ++ i){ sum += a[i]; if (a[i] == 0 && zero){ LL id = 0, val = 0; for(auto &i : cnt){ if (val < i.second){ val = i.second; id = i.first; } } sum -= id; ans += val; cnt.clear(); }else if (a[i] == 0){ zero = true; cnt.clear(); }else if (!zero && sum == 0) ++ ans; cnt[sum] ++; } if (zero){ LL id = 0, val = 0; for(auto &i : cnt){ if (val < i.second){ val = i.second; id = i.first; } } sum -= id; ans += val; } cout << ans << '\n'; } return 0; }
D. ConstructOR (CF 1748 D)
题目大意
给定,要求给一个 ,满足
- 被 整除
- 被 整除
其中为二进制或运算
其中
解题思路
构造题,尽量从简入手。
不妨假设。由于,而 ,我们考虑高 位,可以列出以下方程
如果是偶数, 是不存在逆元的,如果此时 是奇数,那么该方程无解。但如果是偶数,我们可以所有数提一个 出来,此时方程的成立条件并不会变化,可以继续相同判断。
假设提了 个 ,方程就变为
此时必有一个数是奇数,如果是奇数则无解,如果 是奇数,则可解出
继而得到 。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; LL qpower(LL a, LL b, LL mo){ LL qwq = 1; while(b){ if (b & 1) qwq = qwq * a % mo; a = a * a % mo; b >>= 1; } return qwq; } LL exgcd(LL a, LL b, LL &x, LL &y) { if (b == 0) { x = 1; y = 0; return a; } LL ret = exgcd(b, a % b, y, x); y -= a / b * x; return ret; } LL get_inv(LL a, LL M) { static LL x, y; assert(exgcd(a, M, x, y) == 1); return (x % M + M) % M; } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ LL a, b, d; cin >> a >> b >> d; bool ok = true; int sign = 0; while(!(d & 1)){ if ((a & 1) || (b & 1)){ ok = false; break; } d >>= 1; a >>= 1; b >>= 1; ++ sign; } if (!ok) cout << "-1" << '\n'; else{ LL ab = (a | b); LL m = d - ab % d; LL x = m * qpower(get_inv(2, d), 30 - sign, d) % d; x <<= 30; x += (ab << sign); cout << x << '\n'; } } return 0; }
E. Yet Another Array Counting Problem (CF 1748 E)
题目大意
给定一个整数序列,记f(l,r)表示子序列 中值最大且下标最小的下标。
问有多少个整数序列 ,其 与 相同。其中
解题思路
又是最值又是下标,容易想到笛卡尔树,实际上就是问有多少个序列的笛卡尔树和序列 一样。
设表示下标为取值为的方案数,在笛卡尔树上直接即可。
转移的时候记录下前缀和就好了。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; #define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i) #define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i) const int N = 1e6 + 8; const LL mo = 1e9 + 7; int n, rt, m; LL val[N], ans; LL G[N][2]; void build() { static int s[N], last; int p = 0; FOR (x, 1, n + 1) { last = 0; while (p && val[s[p - 1]] < val[x]) last = s[--p]; if (p) G[s[p - 1]][1] = x; if (last) G[x][0] = last; s[p++] = x; } rt = s[0]; } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--){ cin >> n >> m; for(int i = 1; i <= n; ++ i) cin >> val[i]; build(); vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0)); function<void(int)> dfs = [&](int u){ if (G[u][0] == 0 && G[u][1] == 0){ fill(dp[u].begin(), dp[u].end(), 1); return; } LL lsum = 0, rsum = 0; LL lson = G[u][0]; if (lson != 0) dfs(lson); LL rson = G[u][1]; if (rson != 0) dfs(rson); for(int i = 1; i <= m; ++ i){ rsum += dp[rson][i]; rsum %= mo; dp[u][i] = (lson == 0 ? 1 : lsum) * (rson == 0 ? 1 : rsum) % mo; lsum += dp[lson][i]; lsum %= mo; } }; dfs(rt); ans = 0; for(int i = 1; i <= m; ++ i) ans = (ans + dp[rt][i]) % mo; cout << ans << '\n'; for(int i = 0; i <= n; ++ i) G[i][0] = G[i][1] = 0; } return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/16892830.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步