CF补题 970-Div.3
CF补题 970-Div.3-20241217
Dashboard - Codeforces Round 970 (Div. 3) - Codeforces
A:
题目大意:给出 \(a\) 个 \(1\) 和 \(b\) 个 \(2\) 组成的序列,可以在其中加入 \(+or-\) 号,判断能否使这个序列为 \(0\)
#include <iostream> #define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); using namespace std; int a, b; int main() { streampreset(); int T; cin >> T; while (T--) { cin >> a >> b; if (a % 2 == 0 && b % 2 == 0) cout << "YES" << endl; else if (b % 2 == 1 && a % 2 == 0 && a / 2 > 0) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
判断两种情况
- \(a\) 和 \(b\) 都为 \(2\) 的整数倍,即两种都能自身两两相互抵消
- \(b\) 不为 \(2\) 的整数倍,判断能否从 \(a\) 中取出两个 \(1\) 组成一个 \(2\),并且 \(a\) 必须满足自身能被 \(2\) 整除
不满足以上条件则不能组合为 \(0\)
B:
题目大意:给出一个由 \(0\) 和 \(1\) 组成的序列,能否组合成一个外围为 \(1\) 内部全为 \(0\) 的正方形矩阵,第\(((i−1)∗c+j)\)个字符为矩阵 \(i·j\) 的第 \(i,j\) 个元素
#include <iostream> #include <string> #include <math.h> #define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); using namespace std; int n; string s; int main() { streampreset(); int T; cin >> T; while (T--) { cin >> n >> s; double edge = sqrt(n); bool ans = 1; if ((int)edge != edge) { cout << "No" << endl; continue; } for (int i = 0; i < edge; i++) { for (int j = edge * i; j < edge * (i + 1); j++) { if (0 <= j && j < edge || edge * (edge - 1) <= j && j < edge * edge || j == edge * i|| j == edge * (i+1) - 1) { if (s[j] != '1') ans = 0; } else { if (s[j] != '0') ans = 0; } } } if (ans) cout << "Yes" << endl; else cout << "No" << endl; } return 0; }
一道模拟题
首先判断能否组成一个正方形矩阵:
double edge = sqrt(n); if ((int)edge != edge) {//如果开方后取整数与浮点数不相同,说明不为平方数 cout << "No" << endl; continue; }
其中0 <= j && j < edge || edge * (edge - 1) <= j && j < edge * edge || j == edge * i|| j == edge * (i+1) - 1
判断是否在外围位置上,如果外围位置上的字符不为 \(1\) ,说明矩阵不成立
C:
题目大意:给出一个区间,求区间内的数组成一个序列的最大长度,序列满足各元素的差另外构成一个等差数列
#include <iostream> #define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); using namespace std; int l, r; int main() { streampreset(); int T; cin >> T; while (T--) { cin >> l >> r; int sub = 0, ans = 0; for (int i = l; i <= r; i += sub) { ans++; sub++; } cout << ans << endl; } return 0; }
十分简单的贪心,每次考虑从左区间出发,等差数列公差为 \(1\)
满足 \(a_{i+1}-a_{i}\) 至少要为 \(i\) ,通过基本数学公式,可以推出 \(l-r\ge a_n-a_1\ge \frac{n\times(n-1)}{2}\)
故也可改写为:
cin >> l >> r; cout << (int)((sqrt(1 + 8.0 * (r - l)) - 1) / 2) + 1) << endl;//向下取整
D:
题目大意:给出一个 \(1\) 到 \(n\) 的一个组合序列,通过 \(i=p_i\) ,当 \(i=j\) 时,说明 \(j\) 可由 \(i\) 到达
现将这个序列上的每个数分别涂上黑白两个颜色,求解从 \(1\le i \le n\),计算每个 \(i\) 最多能到达的黑点个数
#include <iostream> #include <cstring> #include <string> #define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); using namespace std; int p[200010]; char s[200010]; int fa[200010];//存节点的父亲 int ans, ansmem[200010];//存答案和父亲的答案 void dfs(int x, int st) { if (fa[x]) return;//如果当前节点父亲存在,就回溯 fa[x] = st;//把当前节点的父亲设置为st循环发起节点 ans += '1' - s[x];//累加答案 dfs(p[x], st);//搜索下一个数 }//dfs爆搜 void init(void) { memset(fa, 0, sizeof fa); memset(ansmem, 0, sizeof ansmem); }//初始化 int main() { streampreset(); int T; cin >> T; while (T--) { init(); int n; cin >> n; for (int i = 1; i <= n; i++) cin >> p[i]; for (int i = 1; i <= n; i++) cin >> s[i]; for (int i = 1; i <= n; i++) { ans = 0;//初始化答案为0 if (fa[i]) cout << ansmem[fa[i]] << ' ';//如果当前的i存在父节点,就输出父节点记录的答案 else { dfs(i, i);//从这个发起节点开始搜 ansmem[i] = ans;//记录这个点作为父节点的答案 cout << ans << ' ';//输出答案 } } cout << endl;//每组数据换行 } }
首先想到用DFS优化,每次记录当前循环的发起节点,如果在遍历到 \(i\) 的父亲存在时,就输出父节点记录的答案
实测关闭同步流后可以跑到 \(420ms\) 左右,还能接受
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具