牛客网提高五练习
吉老师的题,出的很有水平(应该是T1,T2难度)
同余方程
题意#
给出 询问
分析#
对于前 分,我们可以简单枚举
对于第二个点,我们已知一个数
显然对于 的数据范围,我们只能考虑 或者 的算法
由于如果需要枚举 中的数,时间复杂度将会乘上 ,我们需要考虑直接进行计算
因为确定了 ,不同 的值与 异或的值一定不一样,并且一定是紧密排布的
因此我们可以直接计算出这些数的开头以及结尾,还有 的倍数的个数
对于所有数据
我们考虑将这个问题转换为前缀问题
记 为
那么我们可以将原问题转换为
可以通过二进制分解后选取一部分做上一种情况来求解
代码#
#include <cstdio>
#include <iostream>
using namespace std;
#define qword long long
qword l1, l2, r1, r2, p, ans = 0;
#define M 998244353LL
qword solve(qword l, qword r, qword p) {
if (l % p) l = (l / p + 1) * p;
if (r % p) r = (r / p) * p;
if (l > r) return 0;
return (r / p - l / p + 1) % M;
}
qword solve(qword a, qword b){
qword res = 0;
for (qword i = a; i > 0; i -= i & -i)
for (qword j = b; j > 0; j -= j & -j){
qword m = min(i & -i, j & -j);
qword n = max(i & -i, j & -j);
qword x = ((i - (i & -i)) ^ (j - (j & -j))) | (n - 1);
qword y = x - n + 1;
(res += m % M * solve(y, x, p) % M) %= M;
}
return res;
}
int main() {
cin >> l1 >> r1 >> l2 >> r2 >> p;
if (r1 <= 5000 && r2 <= 5000) {
for (qword i = l1; i <= r1; ++ i)
for (qword j = l2; j <= r2; ++ j) {
qword res = i ^ j;
if (res % p == 0) ans ++;
if (ans > M) ans -= M;
}
}
else ans = solve(++r1, ++r2) - solve(l1, r2) - solve(r1, l2) + solve(l1, l2);
cout << (ans + M) % M << endl;
}
旅行
题意#
每条边至少走一次,从 出发回到
解析#
应为这是一个闭合回路,如果我们将重复走的边进行拆分,那这张图就是个欧拉回路
因此,我们要保证每个点的度都是偶数
考虑添加哪些边使得每个点的度是偶数
由于每加一条边,只会改变两个点的度,并且这个度是可以传递的 最短路 + dp? 时间暴了
发现由于边权全部是 的幂次,并且幂次高的一定比所有幂次小的的和大,所以我们只要选取了高幂次的,我们就可以通过选取低幂次来降低总的
由此,我们可以发现我们最终选取的值全部都在这个图的 MST 上
那么原问题将转变成选取那些边,可以使得这棵树上所有的点的权值全是偶数
简单DFS即可
注意取模
代码#
#include <cstdio>
#include <iostream>
using namespace std;
#define qword long long
const int maxn = 5e5 + 10;
int n, m, u[maxn], v[maxn], w[maxn], fa[maxn], d[maxn], ver[maxn << 1], head[maxn << 1], Next[maxn << 1];
long long mi[maxn], tot = 0, ans = 0, edge[maxn << 1];
bool vis[maxn];
#define CH ch = getchar()
const int q = 998244353;
template <class T> inline void read(T &x) {
x = 0; int ch, f = 0;
for (CH; ch < '0' || ch > '9'; CH) if (ch == '-') f = 1;
for (; ch >= '0' && ch <= '9'; CH) x = (x << 1) + (x << 3) + (ch ^ 48);
if (f) x = -x;
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
inline void addEdge(int x, int y, int z) {
ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
}
int dfs(int x) {
vis[x] = 1;
for (int i = head[x]; i; i = Next[i]) {
int y = ver[i], z = edge[i];
if (vis[y]) continue;
int isAdd = dfs(y);
if (isAdd) d[y] ++, d[x] ++, ans += z, ans %= q;
}
if (d[x] & 1) return 1;
else return 0;
}
int main() {
read(n), read(m); mi[0] = 1;
for (int i = 1; i <= m; ++ i) {
read(u[i]), read(v[i]); fa[i] = i;
d[u[i]] ++, d[v[i]] ++; mi[i] = (mi[i - 1] << 1) % q;
ans += mi[i]; ans %= q;
}
for (int i = 1; i <= m; ++ i) {
int uu = u[i], vv = v[i]; // ww -> 2 ^ i
int x = find(uu), y = find(vv);
if (x != y) addEdge(uu, vv, mi[i]), addEdge(vv, uu, mi[i]), fa[x] = y;
}
dfs(1);
cout << ans << endl;
}
串串
题意#
如题所述
解析#
是从 中删除一些字符得到的, 一共有 种
考虑逆过程,我们在 上面插入 个 , 个 来得到
但是直接插入会计算重复,比如 是 ,插入一个 有 种位置,但是得 到的都是相同的结果
为了避免计算重复,我们限制所有统计的插入方案,必须对应着 在 中最 靠前的一次出现,比如在上面的例子中,我们只统计 插入到最末尾的情况。
显然在这样的要求下, 只能插入到 前面或者末尾, 只能插入到 前面或者末尾。因此在一共 个间隔中,除了末尾以外,其他间隔都只能插入一种数字
可以枚举末尾有几个 几个 ,然后用插板法统计方案
代码#
#include <cstdio>
#define qword long long
const int p = 1e9 + 7;
const int maxn = 2010;
int ans, C[maxn << 1][maxn], a, b, c, d;
int main() {
scanf("%d %d %d %d",&a, &b, &c, &d);
C[0][0] = 1;
for (int i = 1; i <= a + b; ++ i){
C[i][0] = 1;
for (int j = 1; j <= i; ++ j)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % p;
}
if(!c || !d){
printf("%lld\n", C[a + b][a]);
return 0;
}
for (int i = 0; i <= a - c; ++ i)
for (int j = 0; j <= b - d; ++ j){
qword ret = C[i + j][j];
(ret *= C[c + d][d]) %= p;
int cq0 = a - c - i, cq1 = b - d - j;
(ret *= C[cq1 + c - 1][c - 1]) %= p;
(ret *= C[cq0 + d - 1][d - 1]) %= p;
(ans += ret ) %= p;
}
printf("%d", ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具