OI

考虑这个排列是怎样生成的。转述一下题意,可以发现,popcount(PiPi+1mod2n)=K\operatorname{popcount}(P_i \oplus P_{i+1 \mod {2^n}})=K,也即全集msk=2N1\text{msk}=2^N-1的一个大小为KK的子集。

由于这是一个环排列,我们不妨令P0=0P_0=0。这样一来,Pi=j=1iSj,Sj=KP_i=\operatorname{\bigoplus}\limits_{j=1}^{i}S_j, |S_j|=K。结合上文可知,这是一个相邻元素二进制位恰相差KK位的格雷码问题。有K=1K=1时,满足条件的SjS_j恰有NN个,也就是NN位格雷码。

考虑推广。我们发现,如果按照类格雷码的方式生成排列,则所有的SjS_j应构成异或空间,其大小应当恰为2N2^N,并且由线性空间知识可以得到,该线性空间的(基的大小)应当恰为NN。这恰好符合NN位格雷码的构造。因此,只要满足上述条件,就一定能够生成符合题意的排列。

可以证明,除了2K(K=NN>1)2\mid K \lor (K=N \land N>1)以外,总是有满足条件的线性空间生成的。

下述解法的时间复杂度O((NK)+2N)\operatorname{O}\left(\dbinom{N}{K}+2^N\right)(更多…)

More
  • 2022年4月11日

以下所有操作均可以通过递归DFS每一位并作相应判断实现。但以下写法实现简洁、常数较小,不失为一种优美的技巧。

下文采用SiS_i表示第ii个集合,msk\text{msk}表示其二进制表示。

简单集合运算

  • S1S2msk1msk2S_1 \cup S_2 \leftarrow \text{msk}_1 \mid \text{msk}_2
  • S1S2msk1 & msk2S_1 \cap S_2 \leftarrow \text{msk}_1\space\&\space\text{msk}_2
  • S1S2msk1 & (msk2)S_1 \setminus S_2 \leftarrow \text{msk}_1\space\&\space(\sim\text{msk}_2)
  • (相对于该二进制数类型最大值的)补集msk\sim\text{msk}
  • 对称差集S1ΔS2msk1  msk2S_1 \Delta S_2 \leftarrow {\text{msk}_1}^{\space\land}\space \text{msk}_2

(更多…)

More
  • 2022年4月9日

介值定理

若有连续函数f:[a,b]Rf: [a, b] \mapsto \mathbb{R},且不失一般性地,令a<b,f(a)<f(b)a< b, f(a)< f(b),则对于任意实数x[f(a),f(b)]x\in [f(a), f(b)],存在c(a,b),f(c)=xc \in (a, b), f(c)=x

容易由实数完备性证明。直观理解,即可以画出一段连续曲线,其两端点分别为(a,f(a)),(b,f(b))(a, f(a)), (b, f(b)),而笔不离开纸面。

离散函数值上的介值定理

若存在函数f(x)Z,xZf(x) \in \mathbb{Z}, x \in \mathbb{Z},且满足f(x)f(x+1)1|f(x)-f(x+1)|\leq 1,则对于a<b,f(a)<f(b)a<b, f(a)<f(b),若有整数x[f(a),f(b)]x \in [f(a), f(b)],存在一个c(a,b),f(c)=xc \in (a, b), f(c)=x

证明显然。

在OI中的实际意义?

我们常遇到这样一类函数:在某些数列上进行统计,邻项函数值之间的差为{1,0,1}\{-1, 0, 1\},如括号序前缀和(‘(‘+1,‘)’1\text{‘(‘} \rightarrow +1, \text{‘)’} \rightarrow -1),则可以通过上述性质判断某两点之间函数值是否存在。

例如CF1695C – Zero Path,本质上路径上数字和是一个满足上述条件的整数离散函数。

再例如CF1658F – Juju and Binary String,可以将题意转化为一个函数f(x)[0,n],x[0,n]xp,f(xp)>0f(x) \in [0, n], x \in [0, n] \land \exists x_p, f(x_p) >0,且满足上述性质;同时有函数g(x)=x,x[1,n]g(x)=x, x \in [1, n],则可以证明一定存在x0,g(x0)=f(x0)x_0, g(x_0)=f(x_0)

More
  • 2022年3月28日

考虑合并若干重叠线段。使其有序化后考虑每两个线段的交,如果其为空则新建一条独立线段,反之合并。

最后应当恰好有77条水平线段,88条垂直线段,否则依题意不可能拼凑出“THUPC\textbf{THUPC}”图形。

DFS搜索组成每个字母的所有可能线段组合。需要合理剪枝,亦可以使用二进制状态压缩减小常数。时间复杂度理论上限为O(75×85)\mathrm{O}(7^5\times 8^5),实际远远达不到。

赛时1A(实际上因为无主函数返回值RE了两次)7KB7\text{KB}代码: (更多…)

More
  • 2022年3月12日

CodeForces Round #755 Div.2 F / Div.1 D Serious Business

此题整整困了我一天半,耗费了好几张草稿纸。实在走投无路,翻看题解,却发现正解曾经近在咫尺。有必要稍作整理。

考虑DP。

错误转移1

这道题与清理班次(《算法竞赛进阶指南》上的一道例题)过于相似,都是“给定一些段落[lp,rp][l_p, r_p],选择其中一些完整覆盖[l0,r0][l_0,r_0],求最小花费”的形式。记上述花费为f(l0,r0)f(l_0, r_0)。但本题与原题不一样之处在于其起点和终点是任意给定的。我的第一反应是枚举在x2x_2位置从第22行转到第33行,利用数据结构维护所有x1x2x_1\leq x_2,在x1x_1转移到第二行,解锁到达x2x_2的最小代价。对于各行前缀和,我们可以利用线段树或树状数组维护。同时我们也知道可以利用数据结构优化在O(nlogn)\mathrm{O}(n \log n)的时间内,计算出对于一个固定的起点l0l_0,所有f(l0,r0),r0[l0,n],p,rp=r0f(l_0, r_0), r_0 \in [l_0, n], \exists p, r_p=r_0的值。 (更多…)

More
  • 2022年3月8日

被这玩意卡了一上午——前天CSP-S模拟的T4需要用到这类问题的转移。为什么题解TMD是错的?

g(i,j,k)g(i,j,k)表示“每个位置有ii类元素可选,且序列中必须包含指定的jj类元素的,长度为kk的序列的个数”。形式化地讲,我们需要统计满足以下条件的序列的个数:p[1,k],apS (S=i);bTS (T=j),p[1,k],ap=b\forall p \in [1,k], a_p \in S\space(|S|=i); \forall b \in T \subseteq S\space(|T|=j), \exists p \in [1,k], a_p=b

通过容斥原理,我们可以计算出至少有0,1,2,,j0,1,2,\dots,jTT中的元素没有被包含在序列中的序列的个数,然后乘上容斥系数累加既是答案。也即: g(i,j,k)=x=0j(1)x(jx)(ix)kg(i,j,k)=\sum\limits_{x=0}^{j}(-1)^x\dbinom{j}{x}(i-x)^{k}。通俗地讲,我们在 jj 个元素中选择 xx 个,并强制使得它们不出现在序列中,其余元素任选。除去组合数的预处理时间,复杂度为O(j)\mathrm{O}(j)。参阅AtCoder ABC 194 F – Digits Paradise in Hexadecimal可以使用上述计算而非DP求解(虽然DP更加简洁直观)

(更多…)

More
  • 2022年3月4日

考虑一棵无根树的生成方式:需要决定一个好的顺序从而达到不重不漏地生成所有 nn 个点的无根树。

类似有向无环图的拓扑排序,可以定义一种无根树的“拓扑排序”:每一轮将当前的叶子删去。这样可以很容易算出直径。设删除的轮数为 rr,则当最终剩余一个孤点时,直径 d=2rd=2r,否则直径 d=2r1d=2r-1。为了生成无根树,我们考虑进行逆操作,在当前的树上加叶子。在此之前,为了不重不漏地对无根树进行表示,我们考虑如下的唯一表示方法:设 dis(x)\text{dis}(x) 为节点 xx 在添加叶子过程中第几轮被添加上树的。对于S={xdis(x)=const}S=\{x\mid \text{dis}(x)=\text{const}\}(也即同一层的节点),显然两棵有标号无根树同构但标号不同,当且仅当每个上述节点xx的叶子节点的标号集合不同。我们总是将 xx 标号小的先行添加为其儿子。这样就不会出现因“两棵树本身同构,子节点编号集合相同导致重复计数的问题”。同时,为了方便、准确地计算,我们严格规定,新加入的 kk 个叶子节点在新树上就是全部的叶子节点。也即在旧树上的所有叶子节点在新树上至少有一个儿子。 (更多…)

More
  • 2022年3月4日

有集合SSS=n|S|=n,则有TS2T=k=0n2k(nk)=3n\sum\limits_{T \subseteq S}2^{|T|}=\sum\limits_{k=0}^{n}2^k\dbinom{n}{k}=3^n。因此,若我们枚举集合,枚举集合的子集的子集做状压DP时,可以得到正确的复杂度O(3n)\mathrm{O}(3^n)而非错误的O(2n×2n)=O(4n)\mathrm{O}(2^n\times 2^n)=\mathrm{O}(4^n)。参见AtCoder ABC 187 F – Close Group

可以这样证明:考虑某个子集的子集PTSP \subseteq T \subseteq S,则SS中的每个元素有三种状态:aPa\in PaP,aTa \notin P, a \in TaT,aSa \notin T, a \in S。显然这样可以唯一表示SSTT以及PP,对应了所有子集的拆分方案。故原式成立。

More
  • 2022年2月24日

UPD 02.15:更新了区间操作部分。

约莫半月前练习专题时,发现几道解法多样的题目,其中需要运用一些中高级数据结构。苦于之前没有学习过平衡树,便挑选了一种易于上手、实现简单的平衡树学习,也即FHQ Treap。由11年国家队队员范浩强发明。

为书写方便,文章中可能将直接使用pp代指某节点的随机权值,val\text{val}代指节点关键码(即记录的数值),hh代指树高,siz\text{siz}代指子树大小,cnt\text{cnt}代指节点副本数(相同关键码的节点),rt\text{rt}存储根节点编号。

(更多…)

More
  • 2022年2月15日

广义斐波那契数列

定义:任何形如fi=fi1+fi2,f1=x,f2=yf_i=f_{i-1}+f_{i-2}, f_1=x,f_2=y的数列,称为广义斐波那契数列。

F1=F2=1F_1=F_2=1的斐波那契数列的通项公式

Fn=15[(1+52)n(152)n]F_n=\dfrac{1}{\sqrt{5}}\left[\left(\dfrac{1+\sqrt{5}}{2}\right)^n-\left(\dfrac{1-\sqrt{5}}{2}\right)^n\right]

证明方法多样,可惜我都不会知乎 – 斐波那契通项公式是怎样推导出来的?

下文中以FnF_n代指斐波那契数列的第nn项,fnf_n代表广义斐波那契数列的第nn项。

(更多…)

More
  • 2022年2月8日