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\) 左右,还能接受

posted @   才瓯  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示