news 2026/4/23 17:00:34

【记录】AT_abc406模拟赛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【记录】AT_abc406模拟赛

我感觉自己糖的没边了


https://www.luogu.com.cn/problem/AT_abc406_c

因为恰好一个,所以要找的是类似波形函数的一段。

更确切地说,是前一段递增的最后一个和后一段递增的第一个。

所以只要求出所有递增段,枚举起始结尾即可。

https://www.luogu.com.cn/problem/AT_abc406_d

给了 2e5,还给了 2.5s。肯定是 nlog 级别。

按行列分类开两个 set,放编号,删的时候两个一起删。

https://www.luogu.com.cn/problem/AT_abc406_e

#include<bits/stdc++.h> using namespace std; typedef unsigned long long ULL; const ULL P = 998244353; // 模数 const int N = 65; // 最大位数,ULL 通常为 64 位,这里开大一点防止越界 ULL C[N][N], S[N][N]; // C[i][j]: 组合数 C(i, j); S[i][j]: 长度为 i 的二进制数中恰有 j 个 1 的所有数的和 // 计算 x 的二进制中 1 的个数 (popcount) int getbit(ULL x) { int sum = 0; // 从高位向低位扫描,其实直接用 __builtin_popcountll(x) 更快,但手写更通用 for (int i = 59; i >= 0; i --) if (x & (1ull << i)) { sum ++; } return sum; } // 核心计算函数:计算 1 到 n 中 popcount 为 K 的数的和 ULL calc(ULL n, int K) { ULL ans = 0; // 从高位到低位枚举每一位 i for (int i = 59; i >= 0; i --) { // 如果 n 的第 i 位是 0,则不能在这一位填 0 来构造“小于 n”的数(因为前缀必须和 n 一样,这一位填 0 会导致前缀变小,但 n 这里是 0,填 0 就等于前缀一样了,逻辑上这一位只能填 0,无法产生分支) // 只有当 n 的第 i 位是 1 时,我们才可以尝试在这一位填 0,从而让后面的位任意取,构造出小于 n 的数 if ((n & (1ull << i)) == 0) { continue; } // 计算 n 在高于 i 位的部分(即 i+1 到最高位)已经有多少个 1 // n >> (i + 1) 移除了低 i+1 位,保留了高位前缀 int t = K - getbit(n >> (i + 1)); // 如果还需要填的 1 的个数 t < 0,说明高位前缀的 1 已经超过 K 了,再往后枚举高位前缀只会更长,1 更多,所以直接 break if (t < 0) { break; } // 如果 t > i,说明剩下的位数不够填 t 个 1,这种情况方案数为 0,C[i][t] 和 S[i][t] 自然也是 0(如果初始化正确),可以直接加,也可以特判跳过 // 这里的逻辑是: // 1. S[i][t]: 低 i 位中填 t 个 1 的所有数的总和 // 2. C[i][t]: 低 i 位中填 t 个 1 的方案数 // 3. (n >> (i + 1) << (i + 1)): 提取 n 的高位前缀值(将低 i+1 位清零) // 公式:ans += (低位总和) + (高位前缀值 * 方案数) // 注意:这里当前位 i 填的是 0,所以高位前缀就是 n 的高位部分 ULL prefix_val = (n >> (i + 1)) << (i + 1); // 高位部分的值 // 防止 prefix_val 过大,先取模。虽然 prefix_val 可能超过 ULL 范围吗?不会,n 是 ULL,但取模是为了后续乘法不溢出 // 实际上 prefix_val % P 是安全的 ULL term1 = S[i][t]; // 低位贡献 ULL term2 = (C[i][t] * (prefix_val % P)) % P; // 高位贡献 ans = (ans + term1 + term2) % P; } // 最后检查 n 本身是否满足条件,如果满足则加上 n return (ans + n * (getbit(n) == K)) % P; } int main () { ios::sync_with_stdio(false); cin.tie(0); // 预处理组合数 C[i][j] = C[i-1][j-1] + C[i-1][j] memset(C, 0, sizeof(C)); C[0][0] = 1; for (int i = 1; i <= N - 5; i ++) { C[i][0] = 1; for (int j = 1; j <= i; j ++) { C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % P; } } // 预处理 S[i][j]: 长度为 i 的二进制数中,恰好有 j 个 1 的所有数的数值之和 // 递推关系推导: // 考虑长度为 i 的数,最高位(第 i-1 位)可以是 0 或 1 // 1. 最高位填 0: 剩下的 i-1 位中选 j 个 1。贡献为 S[i-1][j] // 2. 最高位填 1: 剩下的 i-1 位中选 j-1 个 1。 // 此时最高位贡献了 2^(i-1)。这样的数共有 C[i-1][j-1] 个。 // 最高位的总贡献 = 2^(i-1) * C[i-1][j-1] // 低位的总贡献 = S[i-1][j-1] // 综上: S[i][j] = S[i-1][j] + S[i-1][j-1] + 2^(i-1) * C[i-1][j-1] memset(S, 0, sizeof(S)); for (int i = 1; i <= N - 5; i ++) { for (int j = 1; j <= i; j ++) { // 第一部分:最高位填 1 带来的低位和 + 最高位本身的值 * 方案数 ULL high_bit_val = (1ull << (i - 1)) % P; ULL count = C[i - 1][j - 1]; S[i][j] = (S[i - 1][j - 1] + high_bit_val * count % P) % P; // 第二部分:最高位填 0 的情况 S[i][j]= (S[i][j] + S[i - 1][j]) % P; } } int T; cin >> T; while (T --) { ULL n; int K; cin >> n >> K; cout << calc(n, K) << "\n"; } return 0; }

https://www.luogu.com.cn/problem/AT_abc406_f

树转序列。

#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 3e5 + 10; struct node { int x, y; } a[N]; vector<int> G[N]; int dfn[N], tsp, dep[N], siz[N]; void dfs(int x, int fa) { tsp ++; dfn[x] = tsp; dep[x] = dep[fa] + 1; siz[x] = 1; for (int y : G[x]) if (y != fa) { dfs(y, x); siz[x] += siz[y]; } } LL c[N]; int n; void add(int x, LL d) { if (x == 0 || x > n) { return ; } for (int i = x; i <= n; i += (i & -i)) { c[i] += d; } } LL getsum(int x) { if (x == 0) { return 0; } if (x > n) { x = n; } LL sum = 0; for (int i = x; i >= 1; i -= (i & -i)) { sum += c[i]; } return sum; } int main () { ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 1; i < n; i ++) { cin >> a[i].x >> a[i].y; G[a[i].x].push_back(a[i].y); G[a[i].y].push_back(a[i].x); } tsp = 0; dep[0] = 0; memset(siz, 0, sizeof(siz)); dfs(1, 0); int q; cin >> q; memset(c, 0, sizeof(c)); LL sum = n; for (int i = 1; i <= n; i ++) { add(i, 1); } for (int i = 1; i <= q; i ++) { int opt; cin >> opt; if (opt == 1) { int x; LL w; cin >> x >> w; add(dfn[x], w); sum += w; } else { int u; cin >> u; int x = a[u].x, y = a[u].y; if (dep[y] < dep[x]) { swap(x, y); } LL t = getsum(dfn[y] + siz[y] - 1) - getsum(dfn[y] - 1); cout << abs(t - (sum - t)) << "\n"; } } return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 17:00:23

Java、Python、HTML 前端后端如何配合?零基础也能看懂的毕设组合方案

在计算机专业毕业设计中&#xff0c;Java Python HTML 是一套非常经典、实用、易过答辩、项目完整性高的技术组合。很多同学会困惑&#xff1a;这三门语言/技术分别负责什么&#xff1f;怎么拼在一起形成一个完整项目&#xff1f;本文不写一行代码&#xff0c;纯思路讲解&…

作者头像 李华
网站建设 2026/4/18 21:11:00

ADC的基本转换原理

ADC的基本转换原理 ADC参考电压和调理电路

作者头像 李华
网站建设 2026/4/18 21:11:22

AI写专著必备!专业工具大揭秘,开启高效专著撰写之旅

创新是学术专著的核心&#xff0c;同时也是写作过程中最大的挑战。一部优秀的学术专著&#xff0c;不能仅仅是已有研究的简单汇集&#xff0c;它需要提出贯穿全书的独特观点、理论框架或研究方法。在浩如烟海的学术文献中&#xff0c;识别尚未被充分研究的空白是一项艰巨的任务…

作者头像 李华
网站建设 2026/4/18 21:10:50

AI教材生成神器来袭!低查重编写,打造高质量教学资料

在撰写教材的过程中&#xff0c;总会碰碰“慢进度”的诸多困难。尽管框架和资料已然准备就绪&#xff0c;却在具体撰写内容时遇到阻碍——有些话句子研究半天&#xff0c;仍然感觉不够准确&#xff1b;章节之间的衔接&#xff0c;总是难以找到合适的语句&#xff0c;创作常常被…

作者头像 李华
网站建设 2026/4/19 1:02:41

AI写论文大揭秘!这4款AI论文写作工具,写期刊论文超高效!

你是否还在为撰写期刊论文、毕业论文或职称论文而感到困惑呢&#xff1f;当面对大量文献时&#xff0c;就像在大海中捞针&#xff0c;而各种复杂的格式要求又让人应接不暇。反复修改的过程常常让人失去耐心&#xff0c;导致学术写作的效率低下成为许多研究者的烦恼。但别担忧&a…

作者头像 李华