12月杂题选做

杂七杂八算法学了一些,记录一下。

P2483 \(\color{Gold}\bigstar\)

\(k\) 短路板子。

还是很高妙的,先跑出一棵最短路径树,那么一条从 \(1\)\(n\) 的路径一定可以分成树边和非树边,那么一条非树边增加的最短路是固定的。

那么把一个点的所有非树边方案放到一个堆里,每次取出最小值然后走过去,或者不选这条边那么就选堆的左右子树即可。

可以用可持久化可并堆维护一下。

P4102 \(\color{green}\bigstar\)

走恰好若干步显然是一个矩阵乘法。

算个前缀和,可以分治递归,每次算出 \(\le K/2\) 的矩阵即可。

P5288 \(\color{blue}\bigstar\)

感觉不是很难。

容易发现最后一定是一个 \(n\) 为根的菊花,第一问的答案显然就是有多少条线段没有 \(n\)

第二问,把三角剖分树建出,答案就是树的拓扑序数量。

考虑修改,放在树上就是一个左旋或者右旋操作,直接维护。

qoj7932 \(\color{Gold}\bigstar\)

困难题啊。

考虑一个必要条件,两个位如果满足出现位置严格包含了,那么显然一个选了另外一个必须选,这样得到一个 dag,必要条件就是选一个 dag 的前缀。

然后瞎证明一下发现也是充分的。

就是考虑归纳,每次 dag 在一个已有的前缀状态下加入一个点,那么先把这个点对应的序列中的数全部与一下,再和已有的那个状态或一下即可。

那么变成求 dag 割的数量,meet in the middle 一下,先预处理一个点需要选的前置点,然后注意到把一边选的点以及他们在另一边对应的前置点去掉之后,就变成只需要在右边选满足右边条件的点即可,这个可以先预处理即可。

P5417 \(\color{Gold}\bigstar\)

原先做过,现在忘了。

一个排列是后缀数组需要满足的条件就是如果相邻两个要么不等,要么相等那么就去比后面一个。

这个比后面一个这个条件非常难做,想半天不会,事实上完全不用这个条件。

考虑一个 \(\sum c_i=n\) 的情况,稍微想一下就可以发现,把若干个位置放入一个字符,此时对应唯一的一个后缀数组(产生的字符串都相同)。

也就是说,此时的答案是 \(\binom{n}{c_1,c_2,...,c_m}\)

注意到一个后缀数组对应一个不等式链,也就是每个位置和后面一个位置都是 \(<\) 或者 $\le \(,\)<$ 的位置需要钦定前后字符不同,$\le $ 随意,容易发现一个后缀数组对应一个唯一的不等式链。

然后拿一个不等式链来考虑,相当于选若干个位置放到两个 \(<\) 中间,那么此时一种放法还是可以看成是一种字符串,因为两个 \(<\) 中间的字符可以看成全部相等。

总结就是:字符串推出唯一的后缀数组,后缀数组和不等式链双射,然后现在用不等式链推出字符串。

把一段 $\le $ 的看成相同的得到方案,接下来的问题是 \(<\) 是没有被限制的,也就是可以变成 $\le $。

然后就是经典容斥,改一个加一个 \(-1\) 的系数即可。

P4500 \(\color{red}\bigstar\)

这是真的,屁也不会,群论推半天感觉没啥用。

参考link,做了一定的补充(?

注意题目同构的定义是有根的。

首先注意到本质是要求

\[\text{Ans}=\sum_{x\in X/G} (\frac{|x|}{|X|})^k \]

然后注意到每个轨道可以表示为一棵无标号有根树,用 \(T\) 来代替轨道 \(x\),然后令 \(f(T)\) 表示与 \(T\) 同构的方案数,也就是 \(|x|\)

直接瞎数一下,可以得到:

\[f(T)=|T|!\prod_{u\in T} \frac{1}{siz_u}\prod_{u\in T}w_u \]

后面的 \(w\) 是因为 \(u\) 的两个儿子的子树可能同构,需要去掉。

这样有一个好处是式子是乘法而不是加法,取 \(k\) 次方非常方便。

\[\text{Ans}=\frac{1}{((n-1)!)^k}\sum_{|T|=n} f^{k}(T) \]

反手设一个 \(dp_{n,m}=\sum_{|T|=n}f^m(T)\),然后去求。

换用一个求无标号树的套路,把根拿出,然后它的子树相当于一个背包。

\[dp_{n,m}=\frac{(n!)^m}{n^m}[x^n]x\prod_{i=1} \prod_{|T|=i}\sum_{j=0} \frac{x^{ij}f^{jm}(T)}{(j!)^m(|T|!)^m} \]

注意到这个式子有点引荐了,不妨换一下 \(f\) 的定义,修改为:

\[f(T)=\prod_{u\in T} \frac{1}{siz_u}\prod_{u\in T}w_u \]

\(dp,\text{Ans}\) 也同理修改。

\[dp_{n,m}=\frac{1}{n^m}[x^{n-1}]\prod_{i=1} \prod_{|T|=i}\sum_{j=0} \frac{f^{jm}(T)}{(j!)^m}x^{ij}\\ \text{Ans}=n^k dp_{n,k} \]

把后面东西拉出来:

\[A_n=\prod_{i=1} \prod_{|T|=i}\sum_{j=0} \frac{f^{jm}(T)}{(j!)^m}x^{ij}\\ =\exp(\sum_{|T|\le n} \ln(\sum_{j=0}\frac{f^{jm}(T)}{(j!)^m}x^{|T|j})) \]

\(\ln\) 里面东西无法做,但是我们可以去把 \((f^m(T)x^{|T|})\) 换元一下,然后求出这个 \(\ln\) 会在前面乘上的系数,本质上就是多项式复合的定义,但是需要满足 \(\ln\) 有常数项。

可以这么做的本质是,多项式 \(\ln\) 是泰勒展开,因此相当于每一项去卷上 \(\ln x\) 的展开式。

设:

\[B=\ln(\sum_{j=0}\frac{x^j}{(j!)^m}) \]

好处是这个东西只和 \(m\) 有关,可以暴力预处理。

\[A_n=\exp(\sum_{|T|\le n} \sum_{j=0} ([x^j]B)f^{jm}(T)x^{|T|j} )\\ =\exp(\sum_{j=0}([x^j]B) (\sum_{|T|\le n} f^{m}(T)x^{|T|})^j ) \]

现在回想一下我们咋能求出答案,显然是要对 \(dp\) 进行递推,也就是我们需要知道 \(dp\) 的递推式即可。

\[dp_{n,m}=\sum_{|T|=n}f^m(T)\\ =\frac{1}{n^m}[x^{n-1}]\exp(\sum_{j=0}([x^j]B) \sum_{|T|\le n} f^{mj}(T)x^{|T|j}) \]

注意到上下两个东西在后面那个地方是很像的,但是下面是 \(f^{mj}(T)\),考虑修改 \(dp\) 的定义使得可以适应这个东西。

\[dp_{n,m}=\sum_{|T|=n}f^{mk}(T) \]

\(k\) 是题意中选 \(k\) 棵树。

由于只是把 \(m\) 换成了 \(mk\),因此直接可以得到对于新的 \(dp\)

\[B_m=\ln(\sum_{j=0} \frac{x^j}{(j!)^{mk}})\\ dp_{n,m}=\frac{1}{n^{mk}}[x^{n-1}]\exp(\sum_{j=0}([x^j]B_m) \sum_{|T|\le n} f^{mkj}(T)x^{|T|j})\\ =\frac{1}{n^{mk}}[x^{n-1}]\prod_{i} \exp(\sum_{j=0}([x^j]B_m) \sum_{|T|=i} f^{mkj}(T)x^{ij})\\ =\frac{1}{n^{mk}}[x^{n-1}]\prod_{i} \exp(\sum_{j=0}([x^j]B_m) dp_{i,mj}x^{ij}) \]

最后要求的就是 \(dp_{n,1}\)

注意到后面有一个 \(x^{ij}\),也就是 \(ij<n\)(此处是 \(dp\) 下标里的 \(n\)),那么 \(j<n/i\),容易证明对于可能对答案有贡献的 \(dp_{i,j}\) 满足 \(ij\le n\)

终于有做法了,就是考虑记录对于每个 \(m\) 的前缀卷积,然后正常做就行。

最后的问题是 \(O(n^2)\) 的多项式 \(\exp,\ln\)

\[A=e^{B}\\ B=\ln A \]

下面式子两边求导:

\[B'=\frac{A'}{A}\\ xAB'=xA'\\ na_n=\sum_{i=1}^n ia_ib_{n-i} \]

然后就可以做了。

像这种数数题,lg 题解中很多直接给出修改定义后的 \(dp\) 有点离谱了,感觉就是为了讲做法而讲做法,导致像我这样不会做的人完全无法理解思考过程啊。

事实上关键性的步骤是:拆成子树的背包,用 \(B\) 代换掉 \(\ln\),以及重新设计 \(dp\) 意义。

P4339 \(\color{red}\bigstar\)

不会,有时间补。

qoj2601 \(\color{Gold}\bigstar\)

好题,就是代码单薄了一点。

注意题意是 \(\sum a_i+\prod a_i\equiv s \pmod n\)

答案 \(\bmod q\) 显然有用,考虑一些抵消。

对于一个集合 \(a_1,a_2,...,a_q\),考虑它能生成所有序列的和来发现一些性质。

但是考虑这个比校困难,主要是因为数可能会有重复,贡献很难拆开,因此换成求 \(a\) 所有排列(不保证本质不同)的和,最后再去除掉 \(\prod \frac{1}{(c_i)!}\)

那么现在变成 \(a_i\) 数值可能相同,但是我都看成了不同。

但是注意这里如果所有 \(a_i\) 相同,是不能除以 \(p!\) 的,所以要把这种情况扔掉,最后考虑。

考虑左边的 \(\prod_{i=1}^q (a_i+i)\),暴力一拆,相当于一个 \(a\) 的子序列去乘以一个引荐东西。

分析一下这个引荐东西,就是 \([1,q]\) 里面选 \(k\) 个数乘积的和。就是

\[(q-k)!a_1a_2...a_k[x^k]\prod_{i=1}^q(x+i) \]

考虑一下 \(\prod_{i=1}^q (x+i)\) 是啥,注意此处 \(q\) 是质数。

瞎枚举几个 \(q\) 发现中间项都没了。

只会对着结论证明了,结论就是 \(\prod_{i=1}^q (x+i)=x^q-x\),是把系数对 \(q\) 取模意义下。

证明考虑类似费马小定理的证明,取一个正整数 \(a\)

\[\prod_{i=1}^q(x+i) = \prod_{i=1}^q (x+ia) \]

这个是因为模 \(q\)\(ia\)\(i\) 一一对应。

然后暴力拆开每一项,发现 \(x^k\) 右边式子多了一个 \(a^{q-k}\),因此除非 \(k=1,q\),否则右边会出现 \(c_i=a^{q-k}c_i\) 的情况,也就是系数都是 \(0\)

然后单独考虑剩余的两项,一个是全部选,一个是只选一个。

考虑全部选部分,每个排列显然答案相同,本质就是:

\[(p!\prod a_i)\bmod p=0 \]

右边部分就是 \(-\sum a_i(p-1)!=\sum a_i\)

然后再去考虑 \(\sum_{i=1}^q 2^{i-1}a_i\) 这个部分。

单独考虑每一个的贡献,得到:

\[\sum a_i\sum_{j=0}^q 2^{j-1}(q-1)!\\ =\sum a_i(2^q-1)(q-1)!\\ =\sum a_i \]

和前面抵消。

也就是说,如果 \(a_i\) 不是全部相同,对答案无贡献。

那么枚举 \(a_i\) 即可,复杂度 \(O(q\log n)\)

posted @ 2023-12-18 08:10  houzhiyuan  阅读(46)  评论(0编辑  收藏  举报