2024 暑假多校集训
PTZ winter 2021 Day9 A Another Tree Queries Problem
树,带点权\(a\)。
询问 \(x\),求 \(\sum_{i=1}^{n}dis(x,i)a_i\);
修改以 \(u\) 为根 \(v\) 子树加;\(u,v\) 链加。
\(dis(x,i)a_i = dep_x+dep_i-2\times dep_{lca(x,i)}\)
对于 \(i\) 给求出 \(i\) 子树 \(a\) 的和 \(s_i\)
\(\sum_{i=1}^{n}dis(x,i)a_i\)
\(=\sum_{i=1}^{n}(dep_x+dep_i-2\times dep_{lca(x,i)})a_i\)。
\(=(dep_x\times\sum_{i=1}^{n}a_i)+(\sum_{i=1}^{n}dep_i\times a_i)-2\times(\sum_{i=1}^{n}dep_{lca(x,i)}\times a_i)\)。
\(=(dep_x\times\sum_{i=1}^{n}a_i)+(\sum_{i=1}^{n}dep_i\times a_i)-2\times(\sum_{i \in anc(x)}s_i)\)。
trick:一个 \(i\) 对 \(x\) 的贡献算了 \(lca(x,i)\) 到根次,即 \(dep_{lca(x,i)}\)。
搞个树剖 + 线段树,维护 \(s\),操作子树加直接加,链加维护等差数列加,往上的点维护 \(+siz_i\) 的 \(\operatorname{tag}\)。
PTZ summer 2020 Day4 E Longest Common Subsequence
给序列 \(A,B\),值域为 \(\{1,2,3\}\),求最长公共上升子序列,序列长度小于 \(10^6\)。
记:
\(LA_i\) 为 \(A\) 左边第 \(i\) 个 \(1\) 的位置,\(RA_i\) 为 \(A\) 右边第 \(i\) 个 \(3\) 的位置,\(sumA_i\) 为 \(\sum_{j=1}^i [A_j=2]\);
\(LB_i\) 为 \(B\) 左边第 \(i\) 个 \(1\) 的位置,\(RB_i\) 为 \(B\) 右边第 \(i\) 个 \(3\) 的位置,\(sumB_i\) 为 \(\sum_{j=1}^i [B_j=2]\);。
答案为:
\(\max(i+j+\min(sumA_{RA_j}-sumA_{LA_i},sumB_{RB_j}-sumB_{LB_i}))\)
并满足 \(LA_i<RA_j,LB_i<LB_j\)。
假设 \(sumA_{RA_j}-sumA_{LA_i} \le sumB_{RB_j}-sumB_{LB_i}\),则 \(sumA_{RA_j}-sumB_{RB_j} \le sumA_{LA_i}-sumB_{LB_i}\)。
开一棵线段树,\(i\) 从小到大扫描线,满足 \(LA_i<RA_j,LB_i<LB_j\) 的 \(j\) 逐渐变少,在线段树 \(sumA_{RA_j}-sumB_{RB_j}\) 位置维护 \(j+sumA_{RA_j}\),查询 \(i-sumA_{LA_i}+segtree.query(sumA_{RA_i}-sumB_{RB_i})\)。
\(sumA_{RA_j}-sumA_{LA_i} > sumB_{RB_j}-sumB_{LB_i}\) 同理。
1st Ucup Stage 3 F Flower Garden
序列 \(A\) 长度为 \(3n\),\(q\) 个限制 \(a,b,c,d\):
\(\forall i \in [a,b],A_i=0\) 或 \(\forall j \in [c,d],A_j=1\)
并要求 \(0\) 和 \(1\) 个数均不少于 \(n\) 个,求方案。
多测,\(1\le3n,q\le10^5,1\le\sum 3n,\sum q\le10^6\)
\(\forall i \in [a,b],A_i=0\) 或 \(\forall j \in [c,d],A_j=1\) 相当于:
\(\exists i \in [a,b],A_i=1\) 则 \(\forall j \in [c,d],A_j=1\)。
线段树优化建图,每个 \(i \in [a,b]\) 向所有 \(j \in [c,d]\) 连边。
缩点成 DAG,现在求一个闭合子图使 \(siz\) 和在 \([n,2n]\) 中。
假如所有闭合子图每个点的 \(siz\) 都在 \([1,n]\) 中,那么随便选。
否则若闭合子图有点的 \(siz\) 在 \((n,2n]\) 中,那么尽量少选点,选这个点的所有后继,由于这样的点最多 \(3\) 个,暴力即可。
多测 \(\operatorname{tarjan}\) 记得清空 \(\operatorname{dfc}\)!
1st Ucup Stage 0 C Fabulous Fungus Frenzy
有一个 \(n \times m\) 的矩阵,每个位置上有一个字符。另外给了 \(k\) 种模型,第 \(i\) 种模型是一个 \(n_i \times m_i\) 的矩形,同样是每个位置上有一个字符。
操作一把相邻两个位置的字符交换;操作二选择模型 \(i\) 覆盖地图左上角 \(n_i \times m_i\) 的格子。总操作次数限制在 \(4\times10^5\) 次内。操作二次数限制在 \(400\) 次内。
构造一个从初始矩阵到目标矩阵的操作序列,或判断无解。
\(n,m,k\le20\)
考虑倒着做,当左上角 \(n_i \times m_i\) 的格子形如模型 \(i\) 时,可以把这些格子全部变成通配符。
于是可以贪心,不断盖模型 \(i\),使通配符至少增加 \(1\),即判断有没有模型 \(i\) 的字符,盖不上 \(i\) 了再换一个模型。
当所有的模型都已经用不上时,检查当前每种字符的数量判断是否可能经过若干次交换操作后与初始矩阵进行匹配。
交换步数 \(nm(n+m-1)(k+2)\),盖模型次数 \(nm\)。时间复杂度 \(O(n^2m^2(n+m)+(nm+k^2)|\Sigma|)\)
PKU-CPC 2024 D Number Solidity
若 \(a,b>1\),\(a^b\mid x\),\(b\mid x\),则 \(x\) 可以进行一次分解 \(x\to \dfrac{x}{a^b}\)。
一个数 \(x\) 的价值 \(w(x)\) 为 \(x\) 最多能进行的分解次数。
给定 \(n\)(\(1\le n\le10^{14}\)),求 \(\sum\limits_{i=1}^n w(i)\)。
策略肯定是 \(b\) 为 \(x\) 的最小质因子,把所有质因子 \(a\) 满足 \(a^b\mid x\) 的全部分解。
枚举 \(a\),对于每个 \(a\) 算贡献,发现 \(b\) 其实很小,再枚举 \(b\),贡献:
其实 \(b\) 特别小,后面那一段直接 \(2^b\) 容斥即可。
巨难调。
集训队互测 2021 Round 3 Lovely Dogs
给大小为 \(n\) 的树,以 \(1\) 为根,带点权 \(a_i\),并给定常数 \(d\)。
定义:\(x=\prod_{i}p_i^{k_i},f_d(x)=\prod\limits_{i}(-1)^{k_i}[k_i\le d]\)。
对于树上每个节点 \(x\),求所有点对 \((i,j)\) 满足 \(i,j\) 都在 \(x\) 的子树内的 \(f_d(a_ia_j)\) 之和。
\(1\le n\le2\times10^5,1\le d\le20\),保证 \(a_i\) 构成 \(1\) 到 \(n\) 的排列。
首先 \(a_i\) 是排列,映射到树上,所以相当于求 \(\sum\limits_i\sum\limits_j f_d(ij)\)。
令 \(g(x)=\prod\limits_{i}(-1)^{k_i}\),\(h(x)\) 表示最大的 \(t\) 满足 \(t^{d+1}\mid x\)。
考虑当前集合为 \(S\),加入一个数 \(y\),贡献:
如果 \(t\nmid y\),则必然存在质数 \(p\) 使得 \(p^{d+1}\mid x\),则 \(f_d(x)=0\),\(f_d(xy)=0\),故 \(t\mid y\)。
树上莫队可以 \(O(n\sqrt n\ln n)\),但这好像过不去。
\(\operatorname{dsu\ on\ tree}\) 就可以 \(O(n\ln n\log n)\)。
然后解锁了新科技:链分治的 \(\operatorname{dsu\ on\ tree}\),合并 \(x\) 时暴力加入 \(x\) 轻儿子子树所有节点,\(x\) 继承重儿子信息,这样空间 \(O(n)\)。
THUPC 2023 决赛 Freshman Dream
给 \(01\) 矩阵 \(A\),构造 \(01\) 矩阵 \(B\) 满足 \(A_{i,j}\times B_{i,j}\equiv(A*B)_{i,j}\ (\operatorname{mod}\ 2)\),并要求 \(B\) 含有 \(k\) 个 \(1\)。
\(n=100\),\(0\le k\le n^2\),\(a_{i,j}\in\{0,1\}\),所有 \(a_{i,j}\) 均为独立均匀随机。
\(B\) 每一列独立,列方程后高斯消元。
trick:随机 \(01\) 矩阵高斯消元后自由元个数为 \(O(1)\) 级别。
枚举自由元的值,最后还要 \(k\) 个 \(1\),做背包即可。
使用 bitset 优化,时间复杂度 \(O(\frac{n^4}{w})\)。
候选队互测 2022 Round 2 枪打出头鸟
给 \(n\) 个可重集 \(S\),\(q\) 此询问最小的 \(i\) 满足 \(S_1\sim S_{i-1}\) 均能表出 \(x\),但 \(S_i\) 不能。
\(S_i\) 能表出 \(x\) 指存在 \(S_i\) 子集元素异或和为 \(x\)。
线性基求交版题。
线性基求交:
\(A,B\) 求交,假设当前扫到 \(B_i\),\(B_i\) 能被 \(S=A \cap \{B_1,B_2,...,B_{i-1}\}\) 表示(异或)出来。
记选取的元素集合 \(s_1\subseteq A,s2\subseteq \{B_1,B_2,...,B_{i-1}\}\),则 \((\bigoplus\limits_{a\in s1}a)\oplus(\bigoplus\limits_{b\in s2}b)=B_i\)。
\[(\bigoplus\limits_{a\in s1}a)\oplus(\bigoplus\limits_{b\in s2}b)=B_i \]\[\bigoplus\limits_{a\in s1}a=(\bigoplus\limits_{b\in s2}b)\oplus B_i \]\[\bigoplus\limits_{a\in s1}a=\bigoplus\limits_{b\in(s2\cup\{B_i\})}b \]记 \(w=\bigoplus\limits_{a\in s1}a\),\(w\) 既能被 \(A\) 表出也能被 \(B\) 表出,\(w\in(A\cap B)\)。
但我们只知道 \(S\),不知道 \(s1\) 的元素,于是我们可以开一个辅助数组 \(T\),\(T_i\) 表示 \(S_i\) 中属于 \(A\) 的部分。设 \(B_i=\bigoplus\limits_x S_x\),则 \(w=\bigoplus\limits_x T_x,w\in(A\cap B)\)。
但假如 \(B_i\) 不能被 \(S=A \cap \{B_1,B_2,...,B_{i-1}\}\) 表示出来,将 \(B_i\) 插入 \(S\)。设 \(B_i=(\bigoplus\limits_x S_x)\oplus B'_i\),\(B_i\) 最后插入 \(S_p\)(\(S_p=B'_i\)),则 \(w=\bigoplus\limits_x T_x,T_p=w\)。
代码:
#define ull unsigned long long
struct Linear_Basis{
ull lb[64];
inline ull& operator [](int x){
return lb[x];
}
inline void insert(ull x){
for(int i=63;~i;i--)
{
if(x&(1ull<<i)){
if(!lb[i]){
lb[i]=x;
return ;
}
x^=lb[i];
}
}
}
};
Linear_Basis operator &(Linear_Basis A,Linear_Basis B){
Linear_Basis res,S=A,T=A;
memset(res.lb,0,sizeof(res.lb));
for(int i=0;i<64;i++)
{
ull x=B[i],w=0;
if(!B[i]){
continue;
}
for(int j=63;~j;j--)
{
if(x&(1ull<<j)){
if(!S[j]){
S[j]=x;
T[j]=w;
break;
}
x^=S[j];
w^=T[j];
if(!x){
res[i]=w;
break;
}
}
}
}
return res;
}
回归正题,记 \(A_i\) 为 \(S_i\) 的线性基,求出 \(A_1,A_2,...,A_i\) 的交 \(Pre_i\)。
二分 \(x\) 什么时候出现,\(O(q\log^2V)\),过不了。
记录前缀线性基交集变小的位置(最多 \(\log V\) 个),在这些位置上二分,\(O(q\log V\log\log V)\) 可能可以过。
trick:后面的线性空间是前面的线性空间的子空间,按照基的元素出现顺序造一个新的基。(使用前缀线性基记录出现(消失)位置)
直接在这个新的基上查询 \(x\) 什么时候出现,时间复杂度 \(O(q\log V)\),总复杂度 \(O(n\log^2V+q\log V)\)。
CF917D Stranger Trees
给定一张 \(n\)(\(2\le n\le 100\))个节点的无向完全图和这个图的一棵生成树。对于所有 \(i\in[0,n-1]\),求出有多少棵这个完全图的生成树,使得这些生成树与给定的生成树恰好有 \(i\) 条边重复,答案对 \(10^9+7\) 取模。
Matrix Tree 定理,邻接矩阵 \(A\),若 \(i,j\) 是给定生成树上边,则 \(A_{i,j}=x\),否则 \(A_{i,j}=1\),最后求出行列式求值为一个多项式,\(x^i\) 的系数即为 \(i\) 的答案。但求行列式高斯消元要多项式运算,太慢了。
trick:行列式次数不超过 \(n\),先将 \(x=\{1,2,...,n,n+1\}\) 代入求出行列式,再用插值还原出行列式。
2021 集训队互测 Round 1 这是一道集训队胡策题
给出一个 \(n\times n\) 的 \(01\) 矩阵 \(c\),求有多少长度为 \(n\) 的 \(01\) 序列 \(a,b\),满足 \(c_{i,j}=a_i\) 或 \(c_{i,j}=b_j\)。
\(1\le n\le 5\times10^3\),答案对 \(998244353\) 取模。
上面式子取等当且仅当 \(a,b\) 合法。
设 \(x=\sum\limits_{i=1}^na_i\),\(y=\sum\limits_{j=1}^nb_j\)。
\(x,y\) 确定时,\(\sum\limits_{i=1}^n\sum\limits_{j=1}^n[a_i=b_j]=xy+(n-x)(n-y)\) 为定值,贪心使 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n[a_i=c_{i,j}]+[b_j=c_{i,j}]\) 尽量大。
具体地,前 \(x\) 多 \(1\) 的行 \(a_i=1\),前 \(y\) 多 \(1\) 的列 \(b_j=1\)。
设第 \(x\) 多 \(1\) 的行 \(1\) 有 \(num1\) 个,有 \(num1\) 个 \(1\) 的行共 \(k\) 个,要选 \(m\) 个,贡献 \(k\choose m\)。
可能比较抽象,举个例子每行的 \(1\) 个数:\(\{3,3,3,2,2,2,2,1,1\}\),然后 \(x=5\),则第 \(1,2,3\) 行肯定选,第 \(4,5,6,7\) 行选 \(2\) 行,贡献 \(4\choose2\)。
列的贡献同理。
注意 \(x,y\) 可以取 \(0\)。
3rd Ucup Stage 0 I Not Another Constructive!
给一个字符串(字符集大写字母和 \(?\)),将 \(?\) 字符替换为任意大写字母,求最后字符串中 \(N\! AC\) 子序列的数量恰好为 \(k\) 的方案。
\(1\le n\le40\),\(1\le k\le2500\)
可以 \(\operatorname{dp}\),\(dp_{i,n,c,k}\) 表示前 \(i\) 个字符,前面有 \(n\) 个 字符 \(N\),后面有 \(c\) 个 字符 \(C\),已经有 \(k\) 个 \(N\! AC\) 子序列。
转移:
-
\(s_i=N\),\(dp_{i,n,c,k}\gets dp_{i-1,n-1,c,k}\)
-
\(s_i=C\),\(dp_{i,n,c,k}\gets dp_{i-1,n,c+1,k}\)
-
\(s_i=A\),\(dp_{i,n,c,k}\gets dp_{i-1,n,c,k-n\times c}\)
初始 \(\forall c\in[0,n],dp_{0,0,c,0}=1\),时间复杂度 \(O(n^3k)\),发现过不去。
题目只要求一种方案,则 \(dp\) 只需要存 \(0,1\),可以 \(\operatorname{bitset}\) 优化,时间复杂度 \(O(\frac{n^3k}{w})\)。
3rd Ucup Stage 1 D Dwarfs' Bedtime
交互,有 \(n\) 个人(\(1\le n\le 100\)),每个人每天会恰好睡 \(12\) 小时,在整分钟入睡。
你可以在某个时刻查看某个人是睡着还是醒着的,这些时刻必须是不降的,且每个人至多查看 \(50\) 次。
其实 \(n\) 个人可以拆开,所以只考虑一个人的解法。
不妨设此人 \(0\) 时刻睡,先想二分,加入二分的 \(mid\) 时刻他在睡,那还可以往后二分,但你发现如果 \(mid\) 时刻他醒了,那后面就只能一步步跳了。
如果发现 \(l\) 时刻睡,\(r\) 时刻醒,令 \(tim=720\),则只能从 \(l+tim\) 到 \(r+tim\) 暴力跳。
如下图,假设第一次就二分 \(mid\) 到醒的时刻,则 \(l=0\),\(r=mid\),从 \(tim\) 到 \(mid+tim\) 暴力跳。
发现可以平衡一下,跳 \(\sqrt{tim}\) 步询问一次,最后跳散块。
设块长为 \(B\),则需要 \(B+\lceil\dfrac{tim}{B}\rceil\) 次询问。稍一计算,大概 \(50+\),超了点???
trick:尽量利用剩余所有次数
假如我还剩 \(x\) 次询问,则我往前跳 \(x\) 步询问,这样散块最多 \(x-1\) 次就行了。
跳的步数:\(49+48+...+1>720\)
3rd Ucup Stage 1 N (Un)labeled graphs
通信题。
第一次通信:给定一个 \(𝑛\) 个点的有标号无向图 \(𝐺\),输出一个 \(𝑚\) 个点的无标号无向图 \(𝐻\),其中 \(m=n+\lceil\log_2 n\rceil+3\)。
第二次通信:给定 \(𝑛,m\) 和第一次通信输出的 \(H\),求原来的 \(G\)。
\(3\le n\le2024\)
首先 \(H\) 肯定要 \(n\) 个点作 \(G\),关于如何还原编号,可以考虑二进制拆分,用 \(\lceil\log_2 n\rceil\) 个点作一条链拆分编号(原图第 \(i\) 个点连向链上满足 \(i \operatorname{bitand} 2^j=2^j\) 的第 \(j\) 个点)。
现在问题来了,这些点没有标识度,根本找不出那条链,于是考虑整一个有标识度的点 \(A\)。
\(A\) 连向原图和链上所有点,则 \(A\) 是 \(H\) 中度数最大的点。万一链上有和 \(A\) 相等度数的点 \(A'\),其实交换 \(A\) 和 \(A'\) 后的 \(H'\) 和 \(H\) 同构,不影响答案。
但这时需要识别原图和链,建一个点 \(B\) 向原图所有点连边且 \(A\) 连 \(B\),但识别不了 \(B\) 和链头。
于是可以新开一个点 \(C\),因为可以识别 \(A\),\(C\) 作为 \(H\) 中唯一不连 \(A\) 的点也能被识别。
\(C\) 连 \(B\) 和链头以帮助识别,\(deg_B=n+2\)(原图 \(n\) 个点、\(A\)、\(C\)),\(B\) 和链头用度数区分,特殊情况 \(n=3\) 时链头度数也为 \(n+2\),但你其实把图下标改为 \(0-\text{index}\) 就行了。
随便模拟实现,时间复杂度 \(O(m^2)\)。