Codeforces Round #843 (Div. 2)
C. Interesting Sequence(二进制)
题目大意
给定两个大于等于0的数,求满足的最小,若不存在输出-1。
解题思路
首先若肯定无解。
令,若解存在那么它必定处在中。
一次考虑二进制中中的每一位,
- 若,无解(若必然会出现这种情况)。
- 若,无要求。
- 若,此时至少有一个参与运算的数字第位为0,那么,此时在的左边必定无解。
- 若,此时所有参与运算的数字第位为1,那么,在右边无解。
最后若则输出(记录的是检验每个二进制位后的可行解),否则无解。
参考代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void work()
{
ll n, x;
cin >> n >> x;
ll l = n, r = 5e18;
if (n < x)
{
cout << "-1" << endl;
return ;
}
if (n == x)
{
cout << n << endl;
return ;
}
bitset<64> a(n), b(x);
for (int i = 63; i >= 0; --i)
{
if (a[i] == 0 && b[i] == 0)
continue;
else if (a[i] == 0 && b[i] == 1)
{
cout << "-1" << endl;
return ;
}
else if (a[i] == 1 && b[i] == 0)
{
l = max(l, ((n >> i) + 1 << i));
}
else
{
r = min(r, ((n >> i) + 1 << i) - 1);
}
}
if (l <= r)
{
cout << l << endl;
}
else
{
cout << "-1" << endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin >> T;
while (T--)
{
work();
}
return 0;
}
D. Friendly Spiders(数论,图论)
题目大意
给定一张有向图,边的权值为1,每个节点的权值为,只有的两点之间有边。
求给定两点之间的最短路径。
解题思路
求最短路径很简单,用即可,关键是如何快速建边。
将原来的图改造成二分图,左边是原来的点,右边是质因子构成的集合,将左边的点与其所有的质因子连线。
原来的图结构事实上并没有被破坏,只是两点之间的距离变为了原来的两倍。但这大大减少了边的数量。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int pri[N], cnt_p;
int book[N];
int n, s, t;
struct
{
int v, next;
}e[N * 20];
int cnt, head[N * 2];//质数偏移量加N
void get_p()
{
for (int i = 2; i < N; ++i)
{
if (!book[i])
{
pri[cnt_p++] = i;
}
for (int j = 0; pri[j] * i < N; ++j)
{
book[pri[j] * i] = 1;
if (i % pri[j] == 0)
break;
}
}
}
void add(int u, int v)
{
e[++cnt].next = head[u];
e[cnt].v = v;
head[u] = cnt;
}
int trace[N * 2], dis[N * 2];
bool vis[N * 2];
queue<int> q;
bool bfs()
{
q.push(s);
vis[s] = 1;
int v;
while (q.size())
{
int u = q.front();
if (u == t)
return true;
q.pop();
for (int i = head[u]; i; i = e[i].next)
{
v = e[i].v;
if (vis[v])
continue;
dis[v] = dis[u] + 1;
trace[v] = u;
vis[v] = 1;
q.push(v);
}
}
return false;
}
void out(int u)
{
if (u == s)
{
cout << s;
return ;
}
else
{
out(trace[u]);
if (u < N)
cout << " " << u;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
get_p();
cin >> n;
int tt;
for (int i = 1; i <= n; ++i)
{
cin >> tt;
for (int j = 0; j < cnt_p && pri[j] * pri[j] <= tt; ++j)
{
if (tt % pri[j] == 0)
{
add(i, pri[j] + N);
add(pri[j] + N, i);
while (tt % pri[j] == 0)
{
tt /= pri[j];
}
}
}
if (tt > 1)
{
add(i, tt + N);
add(tt + N, i);
}
}
cin >> s >> t;
if (bfs())
{
cout << dis[t] / 2 + 1 << endl;
out(t);
}
else
{
cout << "-1" << endl;
}
return 0;
}
E. The Human Equation(贪心)
题目大意
给定一个数组,求将其全部变为0的最少操作数。
可以进行的操作如下:
选择一个子序列
- 偶数位置元素加1,奇数位置元素减1
- 偶数位置元素减1,奇数位置元素加1
解题思路
求得其前缀和数组,假设选择两个位置,令,在前缀和中体现为,上述操作等价为在前缀和数组中选择任意个元素加1或减1,而将原数组变为0等价于将前缀和数组变为0。
最终的答案为前缀和数组中大于0的最大元素-小于0的最小元素。
参考代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void work()
{
ll t, p = 0;
ll ma = 0;
ll mi = 0;
int n;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> t;
p += t;
mi = min(mi, p);
ma = max(ma, p);
}
cout << ma - mi << endl;
return ;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin >> T;
while (T--)
{
work();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧