zoukankan      html  css  js  c++  java
  • Ideas and Tricks Part II

    33.对于统计答案幂次的技巧

    对于$x^k$,考虑其组合意义:将$k$个不同球放到$x$个不同的盒子里的方案数,直接维护不好维护,那么考虑枚举把这些球放到了哪些盒子里,最后乘上第二类斯特林数和对于的阶乘(保证盒子有序),可以利用一个dp来统计,每次转移的时候考虑是否选择这个盒子$x$

    然后这个做法相当于维护了答案的下降幂,由于下降幂优秀的性质

    $(x+1)^{underline{m}}= x^{underline{m}}+mx^{underline{m-1}}$

    最后利用第二类斯特林数将下降幂转化为普通幂即可

     34.解递归式$f_x=af_{x-i}+bf_{x-j}$

    考虑其组合意义,相当于是爬楼梯,每一次可以走$i$步代价为$a$,或者走$j$步代价为$b$,总代价为每一步代价的乘积,然后问所有走到$n$的方案的代价总和为多少

    可以枚举其中一种步走了多少次

    $sum_{k=0}^{lfloor frac{n}{i} floor} [j|n-ik]a^kb^{frac{n-ik}{j}}inom{k+frac{n-ik}{j}}{k}$

    当然如果代价是每一步之和也是同理

    35.吉司机线段树

    势能函数啥的我也没听懂,不管他

    吉司机线段树以其优秀的性质可以维护各种duliu信息

    然而我只会区间$max/min$(我觉得就这个有点用吧)

    以取$min$为例,就是在线段树中维护最大值$MAX_0$,次大值$MAX_1$和相应出现的次数,注意此处的次大值是要严格小于最大值的(如果不存在次大值那么可以将其赋为$-inf$)

    当每次更新的时候检查当前节点设当前需要取$min$的是$t$

    如果$t geq MAX_0$那么说这个区间什么也不会发生,那么直接返回

    如果 $t leq MAX_1$那么说明更新的区间内会变化的数不止一个,那么继续递归下去

    如果$ MAX_1 < t < MAX_0 $那么这个区间内会被更新的数只有$MAX_0$一个数,那么直接打上减法标记,然后修改$MAX_0$的值为$t$

    时间复杂度大概感性理解一下

    就是区间取$min$操作会使序列中的数趋于相同,每一次第三种操作更新的时候更新一个数,然后第二种情况递归下去,肯定会减少区间中不同数的数量,这样的区间每次询问最多$log$个,那么就是$nlogn$的复杂度

    如果要区间加减,那么就是$log^2n$

    36.DP转移状态有互相转移的情况

    即DP转移建出来的图里面有环的情况

    一句话:利用最短路思想,先把DP的初始状态放入堆中,然后利用状态之间的关系进行转移,跑最短路即可

    其实就是废话

    37.$(x_1+x_2+...+x_n)^k equiv x_1^k+x_2^k+...+ x_n^k(mod k)$k为质数

    $\ equiv sum_{sum k_i=k} inom{k}{k_1,k_2,...,k_n}x_1^{k_1}x_2^{k_2}...x_n^{k_n}$

    $\ equiv sum_{sum k_i=k} frac{k!}{k_1!k_2!...k_n!}x_1^{k_1}x_2^{k_2}...x_n^{k_n}$

    如果$k_1,k_2,...,k_n$中不存在一个$k_i=k$那么系数中一定存在$k$这个因子,那么取模之后系数就变为$0$

    那么上式得证

    38.状压DP的优化

    对于一些分层枚举的状压DP,往往是需要枚举子集进行转移,时间复杂度为$O(3^n)$

    有一种方法可以优化到$O(n2^n)$,枚举子集可以换成尝试将一个点一个点加入到集合中,可以做$0/1$背包来进行转移,但空间需要多开一维

    Yet Another DAG Problem

    39.拆分数优化DP

    对于一些指数级别的DP,可以转化枚举某一个集合中具体是哪些元素为枚举集合的大小,当然这是在保证集合中的数是等价的情况,然后这个DP复杂度就变为拆分数级别的复杂度,一般来说可以跑$40-50$的数据规模

    40.询问集合中第$k$大/小

    就是给定一种生成某一集合的方法,一般是给出一个序列每一个数可选可不选,问集合中第$k$大的数是多少,往往这个集合是巨大的(指数级别),有一种方法可以从小到大构造出集合中的数

    先把序列排好序

    设二元组$(sum,id)$表示当前操作出来的数为$sum$,并且当前考虑到序列中第$id$个数的状态,并且第$id$个数必选

    然后可以进行转移

    $(sum,id) ightarrow (sum+a[id+1],id+1)$

    $(sum,id) ightarrow (sum+a[id+1]-a[id],id+1)$

    相当于是进行$0/1$背包的过程,这个二元组可以用堆来进行维护

    如果可以选多个,那么多一个转移

    $(sum,id) ightarrow (sum+a[id],id)$

    相当于在做无限背包

    再拓展如果每一个数有一个选择上限,那么需要用三元组来记录状态即$(sum,cnt,id)$其中多出来的$cnt$表示当前这个数选了$cnt$次,其他转移同理进行即可

    再再拓展每一个数有一个下限和上限,那么在三元组的基础上,在进行转移到下个数的时候,选下限个数即可,就可以保证满足限制了

    41.快速沃尔什变化

    FWT可以处理形如$C_{ioplus j}=A_i*B_j$形式的卷积

    OR/AND卷积

    首先由于FWT是一个对于多项式的线性变换(说白就是不会出现自己乘自己的情况)

    那么$FWT(A+B)=FWT(A)+FWT(B)$

    由于按位或的特点可以构造出

    $FWT(A)[i]=sum_{i|j=i}A_j$

    这个基于当$i|k=k,j|k=k$时,$(i|j)|k=k$,那么可以通过归纳证明出FWT的确等于这个运算

    考虑如何计算,根据FFT的经验考虑,按首位$0/1$分类记作两个多项式$A_0,A_1$,假设$FWT(A_0),FWT(A_1)$已经计算得出

    那么$FWT(A)=(FWT(A_0),FWT(A_0)+FWT(A_1))$

    如果首位是$0$和$1$的两个数或起来,其首位一定为$1$,那么$FWT(A_1)$不可能贡献到首位为$0$的位置,而原来首位为$0$和首位为1的数或之后,会对应的加到最高位添上了一个$1$的位置上,因为保证了低位或起来一定是原来的低位

    与运算其实是一样的

    $FWT(A)=(FWT(A_0)+FWT(A_1),FWT(A_1))$

    XOR卷积

    大体思路也是和OR卷积相同,只是运算特点不一样,记$cnt(x)$表示$x$在二进制下$1$的个数模$2$的结果

    $cnt(i & k) wedge cnt(j & k)=cnt((i wedge j) & k)$

    那么$FWT(A)[i]=sum_{cnt(i&j)=0} A_j-sum_{cnt(i&j)=1} A_j$,归纳同样可以证明

    结论$FWT(A)=(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))$

    主要说这一个公式的理解

    首先考虑$A_1$,当$A_1$中某一个下标贡献到首位为$0$的位置$i$上时,由于$i$最高位为$0$,在FWT的计算式中的下标$j$,$cnt(i& j)$是不会变的,那么正负号相同,不会变号,所以加上$FWT(A_1)$

    当$A_1$贡献到首位为$1$的位置上时,由于$i,j$的最高位都是$1$,那么$cnt(i& j)$会比原来$+1$,那么会变号,需要减去$FWT(A_1)$

    再考虑$A_0$,由于原来的最高位为$0$,$cnt$的值不会发生改变,计算式中也不会变号,那么无论是$0$还是$1$就直接加上即可

    在推式子的过程中常用的形式

    设$overline{F}$表示$F$的$FWT$结果

    $[x^S]overline{F}=sumlimits_T (-1)^{|Scap T|} [x^T]F$

    $IFWT$就是

    $[x^S]F=frac{1}{2^n}sumlimits_T (-1)^{|Scap T|} [x^T]overline{F}$

    42.min-max容斥

    $max(S)=sum_{varnothing ot=Ssubseteq T}(-1)^{|T|-1}min(T)$

    反过来也同样成立

    证明:

    考虑集合中一个数$x$,设比$x$大的数有$k$个

    考虑$min(T)=x$的集合$T$

    枚举集合大小,其总方案数为$sum_{i=0}^{k}(-1)^iinom{k}{i}=[k=0]$

    那么只有当$k=0$时,$x$有贡献,即$x=max(S)$

    对于期望这个式子也是成立,不过这里$max$表示满足所有条件的期望,$min$表示至少满足一个条件的期望,带入式子即可

    扩展

    $kthmax(S)=sum_{varnothing ot=Tsubseteq S}(-1)^{|T|-k}inom{|T|-1}{k-1}min(T)$

    43.树上高斯消元

    当一些树上的期望DP既要依赖儿子信息又要依赖父亲的信息,此时简单的dfs就无法更新DP值,需要高斯消元

    由于树的特殊性质,树上高斯消元可以做到$O(n)$

    将$dp$方程式改写成,$dp[x]=A_xdp[fa[x]]+B_x$的形式,不断用这个形式更新父亲,直到根节点,最后在根节点解出方程,再反代入解出所有节点的$dp$值

    应用:树上随机游走

    44.最小割

    最小割等于最大流

    利用最小割建图的题目一般会有多种选择,并且会有一些限制条件

    对于多种选择,一般来说会拆点,拆成一条链,链上每一条边就代表一种选择边权为这种选择的价值/代价,然后链的两端分别连向汇点和源点,边权为$inf$(边权设为$inf$的目的就是强制不让选这条边),那么这样在最小割的时候一定会在这条链上选出一个合法且最小的边割掉,使这条路径不连通源点和汇点

    关于限制的连边,一般来说是通过在限制的点中构造出一条路径,并且除了原来在链上的边,其他的边权都是$inf$,这样就可以表达限制某种条件

    说起来很抽象,大概思路就是利用$inf$边来强制不选这条边,然后合理地构造建图

    然后还有一个问题就是如果在建边的时候有负权,那么需要把所有边都加上一个余量,使得都变成正权边,跑出答案之后再减去即可

    ARC107FSum of Abs

    45.最大权闭合子图

    闭合子图就是所有在这个图上的点连出的边指向的节点仍然在这个图上

    在网络流中这个模型很常见

    首先将对于一个有向图中如何求出最大权闭合子图

    对于原图上的边仍然保留并且边流量赋为$inf$

    对于点权为正的点,$s$连向这个点,并且流量设为点权权值

    对于点权为负的点,这个点连向$t$,并且流量设为-点权权值

    最后跑出最小割,所有正点权之和减去最小割即为最大权值

    这个模型可以用来限制选择之间有关系的情况,比如“选了$x$必须选$y$”的情况

    46.利用期望来计数

    对于一些直接计数较难的题,可以考虑用期望来计算,最后乘上方案数即可

    由于期望的线性性,那么可以拆开计算贡献,这样可以只看一个部分而不用关注整体

    47.摩尔投票法

    这是一种可以在$O(n)$时间内统计出众数的东西,其思想值得借鉴

    由于众数在整个序列种出现了超过一半的数量,那么如果用这个数与其他的数两两抵消,那么剩下的一定是那个众数

    那么就可以维护一个栈,如果栈顶元素等于加进去的元素,那么就把这个元素压入栈中,否则就弹出栈顶元素

    48.单调栈维护凸包

    对于一些,加入直线斜率不单调,但是满足当前加入的斜率是当前最优,那么可以用单调栈维护凸包,以上凸包为例,首先要保证栈中的直线斜率是递减的,把所有比当前加入直线斜率大的弹出去,然后凸包内的直线与加入的线的交点应该是要递增的,再利用这个一个限制去弹出栈内的元素

    可以应用于一些DP中

    交通运输

    49.2-SAT

    其主要思想是利用对称性建图,然后保证了一些性质,使选取拓扑序较大的点时,不会存在矛盾

    主要需要注意的是,建图的时候一定要保证对称性

    对于强制某一个点需要选某一个状态的建边将这个状态直接向另一个状态连边

    50.对于矩阵选数的一些问题

    对于每一行每一列只能选一个数,问选出来的数的最大值,这可以转化为二分图最大权匹配问题,就是对于每一个列和行建一个点,不同列和行之间连一条边,边权为行列相交的那个元素大小

    然后费用流跑就行了或者KM

    对于这种只能选一个的问题,需要联想到匹配的模型,因为匹配的点只能最多连出一条边,这可以对应题目的限制

    51.Hall定理

    对于二分图的两部分端点,点集分别记作$X,Y$,其中$|X|leq |Y|$,对于$X$中任意一个子集$W$,记$NW$为$W$中点在$Y$中有连边的点集

    那么对于任意的点集$W$,都有$|W|leq |NW|$时,二分图存在完美匹配

    推论:二分图的最大匹配为$lvert X vert - max{lvert W vert -lvert N(W) vert }$

    52.拉格朗日反演

    对于任意的函数$A,B$

    使得$A=frac{B}{f(B)}$

    有$B=sumlimits_k c_kA^k$

    其中$c_k=frac{1}{k!}{(frac{d}{dB})^{k-1}f(B)^k}_{B=0}$

    相当于$c_k=frac{1}{k!}[f(B)^k]^{(k-1)}|_{B=0}$

    一般来说对于形式幂级数$G$

    将$z$表达成$z=frac{G}{f(G)}$

    其中$f(G)$是一个关于$G$的多项式

    有$G=sumlimits_k c_kz^k$

    $c_k$带入上面的公式计算即可

    这个其中某一项的值可以通过多项式快速幂,在$O(nlogn)$时间算出来

    当然也可以倍增来求$O(nlog^2n)$

    一般用于解一些高次的方程

    53.生成函数的展开

    对于$G=frac{P}{Q}$形式的有理函数

    将$Q$分解为$Q=prodlimits_i (1-r_iz)^{lambda_i}$

    可以写成$G=sumlimits_i sumlimits_{j=1}^{lambda_i} frac{A_{i,j}}{(1-r_iz)^j}$

    对于$A_{i,j}$,可以两边同时乘$(1-r_iz)^{lambda_i}$,再求$lambda_i-j$次导,代入$z=frac{1}{r_i}$

    可以发现的是,右边只剩下一个$A_{i,j}(lambda_i-j)!$,左边带入计算即可

    那么就可以解出来$A_{i,j}$

    那么这个生成函数每一项的就可以简单的计算得到了

  • 相关阅读:
    论架构在嵌软设计中的重要性
    妙用typeof关键字
    说说动态内存分配
    3个实用shell脚本,建议收藏!
    GNU C语法扩展(7)
    Ubunt_配置_nfs(文件挂载)
    Ubunt_配置_samba(文件共享)
    Ubunt_配置_tftp(文件传输)
    Ubunt_配置_net
    驱动_Platform平台总线
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/13874788.html
Copyright © 2011-2022 走看看