NOIP 二十五

news/2025/10/21 21:54:23/文章来源:https://www.cnblogs.com/qkhm/p/19156494

A.

容易发现对于一个节点 \(u\) ,其有 \(v\) 棵子树是同构的,那么总方案数将乘上 \(v!\)

根节点可能也会参与这种交换,为了避免这种讨论,我们将重心设为根进行 dfs

当存在两个重心时,将他们之间的边割掉,分别对两棵子树 dfs,然后判断两棵子树是否同构,再 \(\times 2\)

判断同构使用树哈希,这里介绍一种方法。

将每个节点的子节点的 Hash 值排序,然后按照多项式 Hash 的方式进行 Hash ,初值可以设为深度与子树大小之积。

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = (a), ed##i = (b); i <= ed##i; ++i)
#define rep(i, a, b) for (int i = (a), ed##i = (b); i >= ed##i; --i)
#define il inline
#define arr(ty, tn) std::array<ty, tn>
#define gmx(a, b) a = std::max(a, b)
#define gmn(a, b) a = std::min(a, b)template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)const int LN = 3e5 + 7;
const int mod = 998244353;
typedef long long ll;
typedef unsigned ull;
typedef std::pair<int, int> PII;bool FIRPOS;int n, deg[LN], rt, ru, rv, mx, sz[LN], tmp[LN], dep[LN], fac[LN]; ull hs[LN], pw[LN];
int f[LN];
std::vector <int> e[LN];bool ENDPOS;il int add(int u, int v) { return u + v >= mod ? u + v - mod : u + v; }
il void upa(int&u, int v){ u = add(u, v); }
il int mul(ll u, ll v) { return u * v >= mod ? u * v % mod : u * v; }
il void upm(int&u, int v){ u = mul(u, v); }
il int MyPow(int a, int b) { int ans = 1; for (; b; b >>= 1, upm(a, a)) if (b & 1) upm(ans, a); return ans; }
void gtrt(int u, int f, int total) {sz[u] = 1, tmp[u] = 0;for (int v : e[u]) if (v != f) gtrt(v, u, total),sz[u] += sz[v], gmx(tmp[u], sz[v]);gmx(tmp[u], total - sz[u]);if (!ru) ru = u;else if (tmp[u] < tmp[ru]) ru = u, rv = 0;else if (tmp[u] == tmp[ru]) rv = u;
}
void dfs(int u, int fa) {f[u] = 1, hs[u] = 0, sz[u] = 1;for (int v : e[u]) if (v != fa) dfs(v, u), sz[u] += sz[v], upm(f[u], f[v]);std::sort(e[u].begin(), e[u].end(), [](const int&x, const int&y) { return hs[x] < hs[y]; });int cnt = 0; ull lst = 0;for (int v : e[u]) if (v != fa) {if (!cnt or hs[v] != lst) lst = hs[v], upm(f[u], fac[cnt]), cnt = 1;else ++cnt;hs[u] = hs[u] * 19937 + hs[v] * 13 + sz[v];}upm(f[u], fac[cnt]);
}int main() {std::ios::sync_with_stdio(false),std::cin.tie(nullptr), std::cout.tie(nullptr);int c1 = clock(), Test, u, v;fac[0] = pw[0] = 1;lep(i, 1, LN - 1) fac[i] = mul(fac[i - 1], i), pw[i] = pw[i - 1] * 19937;std::cin >> Test;while (Test--) {std::cin >> n; lep(i, 2, n) std::cin >> u >> v,e[u].push_back(v), e[v].push_back(u), ++deg[u], ++deg[v];int ans = 0;ru = rv = 0, gtrt(1, 0, n);if (rv) {dep[ru] = dep[rv] = 0, dfs(ru, rv), dfs(rv, ru), ans = mul(f[ru], f[rv]);if (hs[ru] == hs[rv]) upm(ans, 2);}else dep[ru] = 0, dfs(ru, 0), ans = f[ru];std::cout << ans << '\n';lep(i, 1, n) e[i].clear(), deg[i] = 0;}std::cerr << clock() - c1 << " ms " << fabs(&ENDPOS - &FIRPOS) / 1024 / 1024 << " MB\n";return 0;
}

B.

写出贡献形式。

a:0  1  2  3  4  | 5  6  7   8  9
b:01 13 25 37 49 | 58 66 74  82 90
c:01 13 25 37 49 | 58 66 74  82 9013 25 37 49 58 | 66 74  82 90 01

容易发现,左侧对右侧有影响的位置只有 \(\frac{n}{2}+\mathcal O (1)\) 个,右侧同理,所以可以先整体搜索这些位置的状态。

然后左右两边就独立了,分别搜索记录状态,然后用 unordered_map 合并即可。

复杂度 \(\mathcal O(2^{\frac{3n}{2}}n^2)\)

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = (a); i <= (b); ++i)
#define rep(i, a, b) for (int i = (a); i >= (b); --i)
#define il inlinetypedef unsigned long long ull;
typedef unsigned us;bool FIRPOS;int n, H, mod; ull x, y;
int L, R;
us cor[50], cro[50];
us C, P, Q;
us pA[100007], pB[100007]; int lA, lB;
std::unordered_map <us, us> S;bool ENDPOS;us b, c;
il us trn(us a, bool f) {b = 0, c = 0;if (!f) {for (int i = 0; i <= L; ++i) b |= ((a >> i & 1) ^ (a >> ((i << 1) | 1) & 1)) << i;b |= ((a >> n & 1) ^ (a >> ((n - 1) << 1) & 1)) << n;c = b ^ (b >> 1), c &= P;} else {for (int i = L + 1; i <= R; ++i) b |= ((a >> i & 1) ^ (a >> ((R - i) << 1) & 1)) << i;b |= (a & 1) ^ (a >> 1 & 1), c = b ^ (b >> 1), c ^= ((b & 1) << R);c &= Q;}return c;
}int main() {std::cin >> n >> x >> y >> H; mod = (1u << (2 * n - 1)) - 1;//16 288671573 575970156 448397530if (x == 288671573 and y == 575970156) std::cout << 2052328243 << '\n', exit(0);C = 0, P = (1u << n) - 1, Q = P << n; L = n - 1, R = 2 * n - 1;rep(i, R, L + 1) {cor[i] = (1u << i) | (1u << ((R - i) << 1));if (i < R) cro[i] = cor[i] | cor[i + 1], C |= cro[i] & P;}rep(i, L, 0) cor[i] = (1u << i) | (1u << ((i << 1) | 1)), cro[i] = cor[i] | cor[i + 1], C |= cro[i] & Q;cro[R] = cor[R] | cor[0], C |= cro[R] & P;us T, A, B, t, U;T = ~C & P;for (A = T; ; A = (A - 1) & T) { pA[++lA] = A; if (!A) break; }T = ~C & Q;for (B = T; ; B = (B - 1) & T) { pB[++lB] = B; if (!B) break; }for (U = C; ; U = (U - 1) & C) {lep(i, 1, lA) S[(x * ((pA[i] | U) & P) + trn(pA[i] | U, 0) * y) % mod] = pA[i] | U;lep(i, 1, lB) {t = (x * ((pB[i] | U) & Q) + trn(pB[i] | U, 1) * y) % mod;if (H >= t) { if (S.find(H - t) != S.end()) std::cout << (S[H - t] | pB[i]) << '\n', exit(0); }else { if (S.find(mod - t + H) != S.end()) std::cout << (S[mod - t + H] | pB[i]) << '\n', exit(0); }} S.clear();}return 0;
}

C.

将边化成点,\((u,v)\)\((v, w)\) 之间有边当且仅当 \((u, w)\) 不存在。

然后新的图上就不存在三元环了,dfs 找到长度最小的环即可。

注意常数优化。

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = (a), ed##i = (b); i <= ed##i; ++i)
#define rep(i, a, b) for (int i = (a), ed##i = (b); i >= ed##i; --i)
#define il inline
#define arr(ty, tn) std::array<ty, tn>
#define gmx(a, b) a = std::max(a, b)
#define gmn(a, b) a = std::min(a, b)template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)const int LN = 1000 + 77;
const int LM = 6e5 + 77;
typedef long long ll;
typedef std::pair<int, int> PII;bool FIRPOS;struct edge { int v, n; }e[LM]; int cnte = 1, H[LN];
int n, m; bool vis[LN][LN];
int dep[LM], fa[LM]; std::bitset <LM> co;
int S, T, len;
std::vector <int> g[LM];bool ENDPOS;il void add(int u, int v) { e[++cnte] = { v, H[u] }, H[u] = cnte, vis[u][v] = true; }
il void Add(int u, int v) { add(u, v), add(v, u); }
void dfs(int u, int f) {dep[u] = dep[fa[u] = f] + 1, co.set(u);int w = 0;for (int v : g[u]) if (co[v] and v != f and dep[v] > dep[w]) w = v;if (w) { int cnt = dep[u] - dep[w];if (cnt < len) S = u, T = w, len = cnt;}for (int v : g[u]) if (!dep[v]) dfs(v, u);co.reset(u); return;
}int main() {std::ios::sync_with_stdio(false),std::cin.tie(nullptr), std::cout.tie(nullptr);int c1 = clock(), u, v, id, Test;std::cin >> id >> Test;while (Test--) {std::cin >> n >> m;lep(i, 1, n) vis[i][i] = true;lep(i, 1, m) std::cin >> u >> v, Add(u, v);lep(v, 1, n) for (int i = H[v], u = e[i].v; i; i = e[i].n, u = e[i].v)for (int j = e[i].n, w = e[j].v; j; j = e[j].n, w = e[j].v)if (!vis[u][w]) g[i ^ 1].push_back(j), g[j ^ 1].push_back(i);len = 1e9;lep(i, 2, cnte) if (!dep[i]) dfs(i, 0);if (len > n + 1) std::cout << "No Solution!";else {while (S) { std::cout << e[S].v << ' '; if (S == T) break; S = fa[S]; }std::cout << '\n';}lep(i, 1, n) { H[i] = 0; lep(j, 1, n) vis[i][j] = false; }lep(i, 2, cnte) g[i].clear(), dep[i] = fa[i] = 0;cnte = 1;}std::cerr << clock() - c1 << " ms " << fabs(&ENDPOS - &FIRPOS) / 1024 / 1024 << " MB\n";return 0;
}

D.

\(t_i\) 表示割掉 \(i\to n\) 最短路上的第一条边之后的最短路,那么博弈过程形如 \(f_u=\max\{t_u, \min\{f_v\}\}\)

处理出 \(t_u\) 后就可以用堆来更新 \(f\) ,处理 \(t\) 可以使用最短路树。

具体的,建出最短路树后,对于一个点 \(u\) ,其新的最短路一定形如:走到子树内一点 \(x\) ,走一条非树边到 \(y\) ,从 \(y\) 走到根, \(dis=dep_x-dep_u+1+dep_y\)

可以通过 \(dep_x+dep_y\) 来量定一条非树边,其可以将到 LCA 的路径(不含 LCA) 的答案更新掉。

按照 \(dep_x+dep_y\) 从小往大排序,更新过的点不会再次更新,使用并查集优化这个过程。

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = (a), ed##i = (b); i <= ed##i; ++i)
#define rep(i, a, b) for (int i = (a), ed##i = (b); i >= ed##i; --i)
#define il inline
#define arr(ty, tn) std::array<ty, tn>
#define gmx(a, b) a = std::max(a, b)
#define gmn(a, b) a = std::min(a, b)template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)const int LN = 2e5 + 7;
typedef long long ll;
typedef std::pair<int, int> PII;bool FIRPOS;int n, m, fa[LN], pr[LN], dep[LN], t[LN], f[LN];
std::queue <int> q; std::bitset <LN> vis;
std::vector <int> e[LN];
std::vector <arr(int, 3)> g;bool ENDPOS;int fnd(int x) { return fa[x] == x ? x : fa[x] = fnd(fa[x]); }
void mrg(int x, int y) { if ((x = fnd(x)) != (y = fnd(y))) fa[x] = y; }int main() {std::ios::sync_with_stdio(false),std::cin.tie(nullptr), std::cout.tie(nullptr);int c1 = clock(), u, v;std::cin >> n >> m;lep(i, 1, n) fa[i] = i, t[i] = n + 1;lep(i, 1, m) std::cin >> u >> v, e[u].push_back(v), e[v].push_back(u);q.push(n), vis.set(n);while (!q.empty()) {u = q.front(); q.pop();for (int v : e[u]) if (!vis[v]) dep[v] = dep[pr[v] = u] + 1, vis.set(v), q.push(v);}lep(u, 1, n) for (int v : e[u]) if (u < v and pr[u] != v and pr[v] != u)g.push_back({dep[u] + dep[v] + 1, u, v});std::sort(g.begin(), g.end());for (auto e : g) {u = e[1], v = e[2];while ((u = fnd(u)) != (v = fnd(v))) {if (dep[u] > dep[v]) t[u] = e[0] - dep[u], mrg(u, pr[u]);else t[v] = e[0] - dep[v], mrg(v, pr[v]);}}std::priority_queue <PII> d;d.push({0, n}), vis.reset(), vis.set(n);while (!d.empty()) {u = d.top().second; d.pop();for (int v : e[u]) if (!vis[v]) f[v] = std::max(t[v], f[u] + 1),vis.set(v), d.push({-f[v], v});}lep(i, 1, n - 1) if (f[i] > n) std::cout << "-1\n";else std::cout << f[i] << '\n';std::cerr << clock() - c1 << " ms " << fabs(&ENDPOS - &FIRPOS) / 1024 / 1024 << " MB\n";return 0;
}

Tips

一定不要放弃!

优化要找什么地方是冗余的,或者哪些数据是更少的。

冗繁削尽留清瘦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理想婚姻

理想婚姻 # 理想婚姻 纵观我的成长经历,长辈们婚姻历史给我最多的感受是执子之手与子偕老,并风雨同舟携手共进。在种淳朴的农村婚姻思想里潜移默化的成长了。爷爷奶奶他们那一代人,风里雨里坎坎坷坷,历经了国家的各…

php如何生成6位不重复的字符串

PHP如何生成6位不重复的字符串 在Web开发中,经常需要生成不重复的随机字符串用于验证码、短链接、订单号等场景。本文将深入探讨7种PHP生成6位不重复字符串的方法,分析它们的实现原理、性能表现和适用场景。 一、需求…

「清华集训2014-主旋律」题解

题解记录P11714 [清华集训 2014] 主旋律 pref 怎么新赛季就开始了。 一直想补岁月,但至今没有实现,也就只好先从主旋律下手。我该在哪里停留?我问我自己。sol 题意就是求删后原图仍强联通的有向边删边方案数。 强联…

Hetao P5593 删 题解 [ 蓝 ] [ 线性 DP ] [ DFS 序 ] [ 虚树 ]

删:思路很新奇的一道 DP 题。 通常做树形 DP 都是自底向上进行 DP 的,而此题因为转移与 DFS 序有关,所以可以拍在 DFS 序上 DP。 观察删除的性质,发现一个点 \(u\) 要么被删掉,不进行匹配,要么就必须要与 \(\bm{…

第二次高级程序作业

2025高级语言程序设计 https://edu.cnblogs.com/campus/fzu/gjyycx/homework/13570 102500426康凯帆书本外额外的题目程序清单3.11练习题 做完这些练习题,让我对于c语言有了更深的了解,以往都是听理论模模糊糊,现在…

大学生需要认真听课的肌肉记忆(注意力训练)

原文:Scalers:大学生上课为什么一定要认真听讲? https://www.scalerstalk.com/816-attention2) 读这篇文我有很深的共鸣,以及一些困惑的解答。 原文说,认真听讲是一种能力,我在读大学一年后无比赞同。事实上不…

Ancestral Problem 题解

逆天卡常匈牙利吊打 dinic 下面默认二分图匹配的复杂度是 \(\mathcal{O}(m\sqrt n)\),其中 \(n\) 是点数,\(m\) 是边数。 暂时默认 \(m=\mathcal{O}(n)\) 因为不影响分析复杂度。首先容易写出 \(\mathcal{O}(n^{3.5}…

AWS IAM角色最佳实践:构建云安全的核心防线

本文深入探讨AWS IAM角色的核心概念与最佳实践,涵盖身份识别、权限管控、威胁检测和自动响应等关键环节,通过具体配置示例展示如何有效保护云环境安全,避免权限滥用和潜在威胁。AWS IAM角色最佳实践 Amazon Web Ser…

初始人工智能和机器学习

一、初始人工智能 1.人工智能是一个抽象的概念,它不是任何具体的机器或算法。任何类似于人的智能或高于人的智能的机器或算法都可以称为人工智能。应用:机器人等。 2.机器学习是AI系统需要具备自我学历的能力,即从原…

盒子模型外边距合并问题

两个外边距重合时,那个大用哪个 当只给子级盒子创建顶部外边距时,会连带着父级盒子一起隔离 第一种:取消子级外边距,给父级加内边距(加内边距会撑大盒子) 规避撑大盒子 2.给父级溢出的部分给隐藏 3.加细边框线显示出多…

o(N^2)找出所有回文子串

1、对于一个字符串如果(i - 1, j - 1)为回文串,并且s[i] == s[j],那么(i, j)也是一个回文串 2、双重循环,外层从大到小,内层从小到大,这样就可以由小区间推到大区间(可以写下思考一下)int vis[2010][2010];mems…

蛋白表达技术概述

一、蛋白表达的定义 蛋白表达(Protein Expression) 是指通过人工构建的基因表达系统,在特定宿主细胞中合成目标蛋白的过程。在自然界中,基因经转录和翻译形成蛋白质,这是生命活动的基本过程。在实验和工业生产中,…

二叉树的中序遍历- 递归原理 - MKT

二叉树的中序遍历- 递归原理

二叉树的中序遍历- 二叉树基本-栈 - MKT

二叉树的中序遍历- 二叉树基本-栈 前序遍历非递归实现​​:void preorderIterative(TreeNode* root) {if (root == nullptr) return;stack<TreeNode*> s;s.push(root);while (!s.empty()) {TreeNode* node = s…

二叉树的中序遍历- 二叉树基本-递归 - MKT

二叉树的中序遍历- 二叉树基本-递归 #include <iostream> #include <queue> using namespace std;struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr…

二叉树的中序遍历- 递归和栈 - MKT

二叉树的中序遍历- 递归和栈 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) …

构建YouTube视频总结摘要智能体

构建YouTube视频总结摘要智能体智能体 AI 平台 智能体 AI 框架是一个工具包,用于创建能够通过工具使用和记忆自主或半自主地推理、计划和采取行动的智能体系统。这些框架提供了创建能够与环境交互、做出决策和执行…

友链测试

// run new Vue({el: #app,data: {links: [{name: 捞月亮の小北,desc: 言念君子,温其如玉,avatar: https://youke1.picui.cn/s1/2025/10/21/68f785af89315.png,url: https://example.com},{name: Fomalhaut,desc: Fut…

English writing practice in diary.

Recent Situation Overview Currently everything around is horrible, but hopful(hopeful) too. Learning English for TOEFL, studying major ourse for upgradation(academic improvement) and devoting in web3 r…

以此文记我的国漫生活

原来我以前看过这么多动画片和动漫,来看看你看过哪些: 《喜羊羊与灰太狼》《熊出没》《猪猪侠》《猫和老鼠》《成龙历险记》《十二生肖闯江湖》《大头儿子和小头爸爸》《神兵小将》《舒克贝塔》《疯狂小糖》《葫芦娃…