一些笔记
两个月博客一直处于咕咕咕状态,原因有两个,第一我懒,第二我没图
「2017 山东一轮集训 Day7」逆序对
题意简述:求长度为 \(n\) 的逆序对数恰好为 \(k\) 的排列个数,答案对 \(10^9+7\) 取模。\(n\leq k\leq 10^5\)
首先,第 \(i\) 个数可能会和前面的数产生 \(0,1,...,i-1\) 个逆序对,所以答案等价于求 \(0\leq a_i\leq i-1,a_1+a_2+...,a_n=k\) 的方案数。
解法一:(口胡)
类似付公主的背包,考虑生成函数 \(F(x)=1\times (1+x)\times ...\times (1+x+x^2+...+x^{n-1})\)
然后我们找规律找出 \(\text{Ln}\ (1+x+x^2+...+x^n)\),调和级数算一算,多项式 \(\text{Exp}\) 算一算。不过模数不是 \(998244353\),要用 \(MTT\)
时间复杂度 \(O(n\log n)\)
解法二:
我们曾解决过一个 \(naive\) 的问题,求 \(a_1+a_2+...a_n=k\) 的方案数,但其中有 \(m\) 个数有限制,其中 \(a_{p_i}<b_i\),\(m\leq 20\)
我们知道上界不好处理,考虑容斥,枚举哪几个数突破限制,强制令这些数 \(a_{p_i}\geq b_i\),然后就可以把 \(k-b_i\),转换成 \(simple\) 的问题——不定方程的非负整数解个数。
若 \(a_1+a_2+...a_n=k\),那么不定方程非负整数解的个数为 \(\Large{n+k-1\choose k-1}\)
现在我们也类似刚刚的方法,但这个上界比较特殊,我们可以 \(dp\)。\(f[j][i]\) 表示选了 \(j\) 个数超过限制,\(\sum b=i\) 的方案数。
我们发现 \(dp\) 可以转换成有一个容量为 \(k\) 的背包,物品体积为 \(1,2,...,n\),每个物品只能放一次,求方案数。
如果我们直接背包的话是 \(O(n^2k)\) 的,所以考虑优化,至少我们不能枚举物品体积。
因为这里物品的体积是 \(1,2,...,n\),所以超出限制的数的个数不会超过 \(\sqrt{2k}\) 个。我们再转换问题,求有多少个上升序列长度为 \(j\),和为 \(i\) 时,其中的数 \(\in [1,n]\)
因为是上升序列,我们逆向差分一下,令 \(b_i=a_i-a_{i+1}\),那么序列的和就变成了 \(\sum_{k=1}^{j}b_k\times k\),我们也只用保证 \(b_k>0\)
这样就好 \(dp\) 了。
对于一个长度为 \(j\),和为 \(i\) 的差分后的序列,我们可以把最后一个数 \(+1\),也可以在最后添加一个 \(1\),\(f[j][i]=f[j][i-j]+f[j-1][i-j](i\geq j)\)
但是我们可能会出现 \(a_1>n\) 的情况,这时我们令 \(a_1=n+1\),\(f[j][i]-=f[j-1][i-n-1](i>n)\)
为什么令 \(a_1=n+1\) 是对的呢?
因为每次 \(a_1\) 最多 \(+1\),每当 \(a_1=n+1\) 时,就会把不合法的减掉。如果从状态 \(n+i\) 转移到 \(n+i+1\),那么前面 \(j-1\) 项和为 \(0,1,..,i-1\) 时的情况都被减过了,只用再减去和为 \(i\) 的情况就行了。
这样愉快的 \(dp\) 部分就结束了。
现在只要枚举超过的和 \(i\),把 \(dp\) 完的值乘上容斥系数后加起来再乘上 \(\Large{k-i+n-1\choose n-1}\)就行了。
时间复杂度 \(O(k\sqrt{k})\)
最近啃了一篇 rxd 的论文,关于树上连通块问题的,总结一下。
-
若连通块包含根,可以按照 dfs 序转移,用背包确定切掉哪些子树。
-
点数-边数=1,可以配合上一条使用,就是算出强制包含一个点-强制包含一条边的方案数,具体见完美的集合,因为有个组合数取模我没做。
-
用线段树合并维护整体 dp,PKUSC2019D2T1 就是整体 dp 的板子题,在线段树上维护加法和乘法标记。有一些 dp 是在叶子结点只有有限个状态,可以不用线段树合并,用平衡树合并,比如 ZJOI2019 Minimax 搜索和 PKUWC2018 Minimax。
-
若是连通块最优化或计数问题,可以在深度最浅处统计答案。如 Qtree6,7。
-
动态 dp,一般写树剖就够了,除非出题人恶意卡。对于一些乘法形式的 dp,我们选择记录答案和 0 的个数,额外开个结构体使 0 值可除。
-
基于 LCT 的数据结构 Top Tree (没学,咕咕咕)
脑子不够用了,一些 sb 状压 dp 都想不出来,总结一下。
-
最小/最大表示法,以最小/最大值表示一个集合,若有多个最小值用编号最小的那个。
-
一个 dp 状态难转移,就开两个,如限制每个点子树大小的有根树计数,可以用树/森林的方案数来表示状态。
-
二进制不好表示状态,可以用三进制,如给你一个最长上升子序列方案数。
-
枚举子集 \(O(3^n)\)。