杂题题解

[noiac#551] 矩阵

对于一个 \(n×m\) 的方格纸,求在每个位置填入 \(1∼k\) 的本质不同的方案数。
我们称两个方案是相同的,当且仅当我们可以通过若干次“交换两行”或“交换两列”的操作从一个方案得到另一个方案。
输出答案对 \(10^9+7\) 取模的结果, \(n,m\le45\)

考虑置换群,题目给出的行置换和列置换本质上就是允许重排行列,比较暴力的想法是对两维分别正整数拆分然后组合起来,然后发现较大的一维可以用 dp 做于是背包一下就做完了

code


「SDWC2018 Day2」优秀

先不考虑方案数的限制,考虑画一个折线图出来,可以从下到上按层转移,每两个 1 直接一定会在上一行插入 2 ,每两个 2 一定会在上一层插入 3 ,于是我们枚举当前上一层插入几个可以转移
现在考虑加上方案数的限制,由于方案数要求很小,于是我们直接设 \(f_{i,j,k,l}\) 表示搞完前 i 行,放了 j 个数,还有 k 个空隙,所有合法重排方案数为 l 的数列个数来转移即可
code


Number of M-Coprime Arrays

T 组数据,求满足长度为 n ,所有数都为 m 的约数,相邻两个数互质的数列个数模 \(10^9+7\) 的结果, \(T\le100,n,m\le10^{18}\)

简单思考之后发现每个素数的贡献可以分开算,假设某个素数最多可以选它的 K 次幂,那么有转移式 \(f_n=f_{n-1}+Kf_{n-2}\) ,发现跟素数无关只跟其最高次幂有关,于是 \(miller-rabin\) +矩乘即可
code


yww与校门外的树

转化一下条件发现等价于求所有排列的贡献和
于是考虑从大到小插入每一个数,每次会合并一些连通块,不难发现合并的连通块一定是连续的几段,因此最后合并完后相当于把整个数组拆成了几个连续段,每个连续段连通
考虑设一个连通的连续段的生成函数为 F ,排列的生成函数为 G ,那么显然有 \(G=\frac1{1-F}\)\(Ans=\frac1{1-xF'}\)
多项式求逆即可
code


UR #14 人类补完计划

考虑先硬点出一个基环树集合 S 然后枚举叶子集合统计 S 对答案的贡献: \(2^S\sum\limits_{T\subsetneq S,T\not=\emptyset}(\frac12)^TWay(S,T)\)
\(2^S\) 放进去然后子集反演可以得到贡献的形式为: \(\sum\limits_{T\subsetneq S,T\not=\emptyset}(-1)^T2^{S-T}Way'(S,T)\)
其中 \(Way'(S,T)\) 表示 S 集合为基环树,且叶子集合至少为 T 的方案数,经典集合容斥问题,不过最开始需要统计环的方案数(注意有个小细节是特判二元环)
code


[51nod1538] 一道难题

\(F_m=\sum\limits_{[\sum\limits_{i=1}^na_ib_i=m]}\frac{(\sum\limits_{i=1}^nb_i)!}{\prod\limits_{i=1}^nb_i!}\)
考虑转移一定是 \(F_m\leftarrow F_{m-a_i}\) ,如果知道转移系数就能进一步优化时间复杂度,考虑对于 \(F_m\) ,枚举给非零的 \(b_i\) 加上 1 来转移贡献:

\[\begin{aligned} F_m=&\sum\limits_{[\sum\limits_{i=1}^na_ib_i=m]}\frac{(\sum\limits_{i=1}^nb_i-1)!}{\prod\limits_{i=1}^nb_i!}*(\sum\limits_{b_i>0}b_i)\\ =&\sum\limits_{i=1}^n\sum\limits_{[\sum\limits_{j=1}^na_jb_j=m,b_i>0]}b_i\frac{(\sum\limits_{i=1}^nb_i-1)!}{\prod\limits_{i=1}^nb_i!}\\ =&\sum\limits_{i=1}^n\sum\limits_{[\sum\limits_{j=1}^na_jb_j=m,b_i>0]}\frac{(\sum\limits_{i=1}^nb_i-1)!}{(b_i-1)!\prod\limits_{j\not=i}^nb_j!}\\ =&\sum\limits_{i=1}^nF_{m-a_i} \end{aligned} \]

于是变成了常系数线性递推的形式,写个模板就过了
注意这个题数据有锅,有两个点貌似满足a[1]>23333需要忽略掉
code


[WC2014] 时空穿梭

考虑枚举最后一个点和第一个点构成的向量,令 \(m=\min\{m_1,m_2,...,m_n\}\)

\[\begin{aligned} Ans=&\sum\limits_{a_1,a_2,...,a_n}C_{\gcd(a_1,a_2,...,a_n)-1}^{c-2}\prod\limits_{i=1}^n(m_i-a_i)\\ =&\sum\limits_{d=1}^mC_{d-1}^{c-2}\sum\limits_{[\gcd(a_1,a_2,...,a_n)==1]}\prod\limits_{i=1}^n(m_i-da_i)\\ =&\sum\limits_{d=1}^mC_{d-1}^{c-2}\sum\limits_{e=1}^{\lfloor\frac md\rfloor}\mu(e)\prod\limits_{i=1}^n\sum\limits_{j=1}^{\lfloor\frac{m_i}{de}\rfloor}(m_i-jde)\\ =&\sum\limits_{T=1}^mF(T)\prod\limits_{i=1}^n(m_i\lfloor\frac{m_i}T\rfloor-\frac{T\lfloor\frac{m_i}T\rfloor(\lfloor\frac{m_i}T\rfloor+1)}2)\\ =&\sum\limits_{T=1}^mF(T)G(m_1,m_2,...,m_n,T) \end{aligned} \]

发现 F 数组可以快速处理出来,而 G 则是一个由 \(n\sqrt m\) 段的分段函数,那么预处理一下区间幂次和然后整除分块就行
code


[hdu6607] Easy Math Problem

\[\begin{aligned} Ans=&\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(i,j)^k\text{lcm}(i,j)[\gcd(i,j)\in P]\\ =&\sum\limits_{d\in P}d^{k+1}\sum\limits_{1\le i,j\le\lfloor\frac nd\rfloor}ij[\gcd(i,j)==1]\\ =&\sum\limits_{d\in P}d^{k+1}\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}i^2\phi(i) \end{aligned} \]

lagrange 插值+min_25筛+杜教筛即可
code


[hdu6715] 算术

不知道为啥当时我打这场初赛的时候菜的连这道题都没秒掉==,顺便一提,当时还有个 cyk 在旁边陪我一起走水
推导可能要用到莫比乌斯函数的一个简单性质: \(\mu(i)^{-1}=\mu(i)\)
然后你发现 \(\mu(\text{lcm}(i,j))=\mu(\frac i{\gcd(i,j)}*\frac j{\gcd(i,j)}*\gcd(i,j))\) ,发现如果这个玩意儿非零的话说明三个乘起来的东西是两两互质的,不妨令这三个玩意儿分别为 \(a,b,c\) ,容易发现 \(\mu(a)*\mu(b)[\gcd(a,b)==1]=\mu(a*b)\) ,因此可以推出 \(\mu(a*b*c)=\mu(a)*\mu(b)*\mu(c)[\gcd(a,b)==1][\gcd(a,c)==1][\gcd(b,c)==1]=\mu(a*c)\mu(b*c)\mu(c)^{-1}[\gcd(a,b)==1]=\mu(c)\mu(a*c)\mu(b*c)[\gcd(a,b)==1]\)
于是可以把答案的式子改成下面这样:

\[\begin{aligned} Ans=&\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\mu(id)\sum\limits_{j=1}^{\lfloor\frac md\rfloor}\mu(jd)[\gcd(i,j)==1]\\ =&\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{e=1}^{\lfloor\frac{\min(n,m)}d\rfloor}\mu(e)(\sum\limits_{i=1}^{\lfloor\frac n{de}\rfloor}\mu(ide))(\sum\limits_{i=1}^{\lfloor\frac m{de}\rfloor}\mu(ide))\\ 令F=&\mu*\mu\\ Ans=&\sum\limits_{T=1}^{\min(n,m)}F(T)(\sum\limits_{i=1}^{\lfloor\frac nT\rfloor}\mu(ide))(\sum\limits_{i=1}^{\lfloor\frac mT\rfloor}\mu(ide))\\ \end{aligned} \]

可以狄利克雷卷积快速处理出 F ,然后每次调和计数算后面的两个 \(\sum\) ,复杂度 \(O(n\log n+Tn\ln n)\)
code


[bzoj5403] marshland

网络流经典模型,考虑把格子黑白染色,发现如果要选择一个黑格子,那么左右的白格子得选一个,上下的白格子得选一个,由于左右的白格子行标号奇偶性相同,上下的白格子行标号奇偶性相同,因此可以把整个矩阵看成三类格子,第一类是行列标号和为偶数且行号为奇数的,第二类是行列标号和为奇数的,第三类是行列标号和为偶数且行号为偶数的,然后建源点向第一类点连边,第一类点向相邻的第二类点入点连边,第二类点入点到出点计算费用,第二类点出点到第三类点连边,第三类点向汇点连边感觉口胡的好复杂
code


UR #5 怎样跑得更快

莫反经典题
先拆一下 \(\text{lcm}\) : \(\frac{b_m}{m^d}=\sum\limits_{i=1}^n\gcd(i,m)^{c-d}(x_ii^d)\) ,然后令 \(b_m\leftarrow\frac{b_m}{m^d},x_m\leftarrow x_mm^d\) ,于是有

\[\begin{aligned} b_m=&\sum\limits_{i=1}^n\gcd(i,m)^{c-d}x_i\\ =&\sum\limits_{D|m}D^{c-d}\sum\limits_{D|T,T\le n}x_T[\gcd(\frac TD,\frac mD)==1]\\ =&\sum\limits_{D|m}D^{c-d}\sum\limits_{DE|m} \mu(E)\sum\limits_{DE|T,T\le n}x_T\\ 令 F(t)=&\sum\limits_{D|T}D^{c-d}\mu(\frac tD)\\ b_m=&\sum\limits_{t|m}F(t)\sum\limits_{t|T,T\le n}x_T\\ \sum\limits_{m|T,T\le n}x_T=&(\frac{b*\mu}F)_m\\ x_m=&\sum\limits_{m|T,T\le n}(\frac{b*\mu}F)_T\mu(\frac Tm)\\ \end{aligned} \]

这就是三次莫反掷地有声吗爱了爱了
code


[AGC040C] Neither AB nor BA

考虑将奇数格子的 A,B 互换,于是不能删除的串变成了 AA 和 BB
于是能消除整个序列的条件等价于 A,B 的个数都不超过 n 的一半,直接计数即可
code


[AGC040D] Balance Beam

考虑对于一个排列,以距离为横坐标时间为纵坐标建立平面直角坐标系,然后画出 A,B 两人的折线,设 \(S=\sum a_i\)
观察图像可以发现 B 随机起点相当于把 B 的折线随机向下平移若干单位长度,那么合法的起点一定是从 0 开始的一段前缀。
设 B 的折线与水平轴交于 \((x,0)\) ,显然是要最大化 \(x\) ,显然当 A,B 的折线只有一个交点的时候的 \(x\) 取到最大值。
然后考虑从 \((x,0)\) 沿着 B 的折线走到交点然后沿着 A 的折线能走到 \((n,S)\) ,我们假设 \((x,0)\) 在第 \(k\) 条边上,于是一定有 \(\sum\limits_{i=k}^n\max(a_i,b_i)\ge S\),结合图形可以得知其意义是每次选择上升更快的一条线走(因为要 \(x\) 最大)最后一定能走到 \((n,S)\) 上方,并且一定能构造出合法的序列使得每个位置都取到 \(\max\)(把 \(a_i<b_i\) 的边放交点前面,把 \(a_i\ge b_i\) 的边放交点后面即可),于是枚举每条边使得该条边和 \(x\) 轴相交然后取最值即可。
code


[USACO19OPEN] Compound Escape P

好像直接裸轮廓线 dp 就能过了
但我考试的时候是 sb 跑去写了状压 dp ,每次转移一整行的状态结果也过了,而且跑的好像蛮快的(
介于这是博主第一次写最小表示法的状态压缩 dp(之前只会括号序),在这里放一个代码。
code


[loj#6440] 万能欧几里得

考虑这么一个神仙算法,我现在从 \((\lfloor\frac rq\rfloor,0)\) 开始沿着线段 \(y=\frac{px+r}q\) 走并记录一个 01 序列,如果走到直线 \(x=k\) 上就往序列里面扔一个 0 ,如果走到直线 \(y=k\) 上就往序列里扔一个 1 ,然后产生 \(A^{1个数}B^{0个数}\) 的贡献。
考虑第 i 个 1 和第 i-1 个 1 间 0 的个数是 \(\lfloor\frac{pi+r}q\rfloor-\lfloor\frac{p(i-1)+r}q\rfloor\)
假如 \(r\ge q\) 那么等价于先扔 \(\lfloor\frac rq\rfloor\) 个 0 进序列,然后 \(r\leftarrow r\mod q\)
假如 \(p\ge q\) 那么每两个 1 之间至少有 \(t=\lfloor\frac pq\rfloor\) 个 0 ,可以令 \(1'=00...0(t个0)1\) ,然后 \(p\leftarrow p\mod q\)
下面讨论 \(r<q\ \text{and}\ p<q\) 的情况,按照类欧几里得的套路应该是交换两维,因此应该转为考虑每两个 0 之间 1 的个数,即考虑每个 0 前面 1 的个数
由于已经知道第 x 个 1 在第 y 个 0 后面的条件:

\[\begin{aligned} y\le&\lfloor\frac{px+r}q\rfloor\\ x\ge&\lceil\frac{qy-r}p\rceil\\ x\ge&\lfloor\frac{qy+p-r-1}p\rfloor\\ \end{aligned} \]

因此我们知道第 x 个 1 在第 y 个 0 前面的条件是 \(x<\lfloor\frac{qy+p-r-1}p\rfloor\) ,于是第 y 个 0 前面有 \(\lfloor\frac{qy-r-1}p\rfloor\) 个 1 ,至此,我们知道新的直线的解析式为 \(f(x)=y=\frac{qx-r-1}p\) ,且 \(x\) 的坐标范围是 \([1,m=\lfloor\frac{px+r}q\rfloor]\) ,且第 i 个 0 和第 i-1 个 0 间 1 的个数是 \(\lfloor\frac{qi-r-1}p\rfloor-\lfloor\frac{q(i-1)-r-1}p\rfloor\) ,这时你发现一个问题是当 \(i=1\) 时,后面一坨是负数,因此把第一个点拎出来特殊处理一下,然后令 \(g(x)=f(x+1)=\frac{qx+p-r-1}p\) ,这样定义域变为了 \([1,m-1]\) ,成为了一个递归子问题,注意到在第 m-1 个 0 后面还有若干个 1 要扔入序列。
总结一下,这种情况的处理方法是先交换两维,然后特殊处理序列头部的第一个 0 及其之前的 1 的贡献,序列尾部的 1 的贡献,去掉这两部分的中间段成为一个递归子问题,问题得以解决。
code


[gym102220A] Apple Business

考虑暴力做法就是对每个询问建一个点,对每个树点建一个点,然后每个询问相当于 \(dep_v-dep_u+1\) 条匹配边,然后费用流。
然后感觉这玩意儿很像二分图,观察一下发现如果把每个询问拆成 \(c_i\) 个点(假设放在二分图左侧),把每个树点拆成 \(a_i\) 个点就真成二分图了,这张图启示我们要尽量把右边的点匹配满,因此我们降低一下左侧点的限制,将每个询问拆成 \(\le c_i\) 个点来进行匹配,使得整张图接近完美匹配,而这个调整的做法可以用贪心来进行阐述。
考虑从按权值大到小依次对每个询问拆点然后匹配,使得拆开的点每个点都成功匹配且拆开的点数最大,发现是可二分的,那么可以二分最后拆开的点数然后用 hall 定理判断合法性。
然后你发现利用 hall 定理来进行判断的话一定是取一个包含路径 \((u,v)\) 的连通块,使得这个连通块剩余可行流量最小,于是此时可以摒弃二分图,转到树上解决问题。
现在相当于是要枚举路径 \((1,u)\) 上的每一个点作为树根 \(rt\) ,然后求包含路径 \((rt,v)\) 的连通块的剩余流量的最小值,由于树高是 \(\log\) 的,这个可以 \(O(\log^2n)\) 树形 dp 轻松解决。
考虑在计算出当前点最大可拆开点数 \(C\) 之后如何更新连通块的剩余流量,由于钦定了根,因此可以直接给 \(v\) 点的剩余流量减去 \(C\) ,然后一路 \(pushup\) 到根。
code


UNR #3 百鸽笼

这个题基本一样。
先考虑最后剩下的是 1 号笼的时候咋做,发现可以容斥在 1 号笼后才被删掉的笼子。
假设枚举的集合为 \(S\) ,把每次选择的笼的标号序列记下来,考虑把序列中不在 \(S\cup\{1\}\) 中的标号以及第 \(a_1\) 个 1 后面的所有标号给删掉。
那么此时的容斥贡献只跟序列长度和序列中涉及的笼数有关。
于是设 \(f_{i,j}\) 表示选了 i 个笼子,标号序列长度为 j 的带容斥系数方案数。
转移就是枚举当前笼子在第 \(a_1\) 个 1 之前出现的次数(注意只能出现 \(0,1,...,a_i-1\) 次)然后组合数乘一下。
最后统计答案即可。
现在要对每个笼子都统计答案,那么我们先把所有笼子都转移一遍,然后枚举笼子撤销转移即可。
code


CTS2019d2t2 重复

考虑补集转化,变为求无穷个串接起来且满足没有一个字典序 \(\ge S\) 的串在其中出现的方案数。
那么对 S 建一个 Kmp 自动机,假设无穷个串后在自动机的 p 点处,考虑再加入一个串进去仍然是无穷个串,因此会从 p 开始走一个长度为 m 的环。
于是只要能成功建出 Kmp 自动机即可枚举起点得到一个 \(O(n^2m)\) 的做法。
考虑这个自动机的限制是对于这个自动机的任意前缀 \(s[1,x]\) ,如果存在 \(s[y,y+x-1]==s[1,x]\) ,那么 \(s[y+x]\ge s[x+1]\)
这样每个点最多存在一条不转移到 0 的边,由这些边构成的转移图呈 \(\rho\) 型。
因此一个点走 m 步之后走回自己可以归纳成两种情况:

  1. 不经过 0 ,那么该点一定沿着 \(rho\) 型图的环一直走,可以 \(O(1)\) 统计
  2. 经过 0 ,那么该点的行走路线可以看成从该点走到 0 ,然后走若干次 0 到 0 的环,然后从 0 走回该点,发现可以看成两个部分:从 0 走到该点又走回 0 ,走若干遍 0 到 0 的环。
    \(f_i\) 表示从 0 开始走 i 步之后回到 0 的方案数,令 \(F\) 为其 OGF ,那么第一部分就是 \(xF'\) ,第二部分是 \(\frac1{1-F}\) ,分别计算然后 ntt 乘起来即可

code


Comet OJ - Contest #16 小 C 的奇妙序列

首先发现方案数是 \((n!)^K\) ,于是可以转化成求所有方案的贡献和。
然后就是 K 次方的常规套路,看成 K 个标号球一起做一件事的方案数。
对于这道题,我们考虑只有一个球的时候是在干什么事,发现是随机一张 DAG 然后从 0 走到 n 的方案数。
考虑用 dp 解决这个问题。
我们发现 K 个球的 K 条路径有重叠部分。
那么对于一条边我们可以把所有要经过它的球的集合状压出来。
然后按 \(0,1,...,n\) 每个点来划分阶段。
假设现在我们在 x 点对应的阶段,有一些球会走跨过 x 的边,有一些球会先走到 x 再走到比 x 大的点。
那么根据上面的分析,可以把走跨过 x 的边的所有球分成若干个集合,每个集合表示集合内的球当前在同一条跨过 x 的边上,设这个状态为 \(f_{x,S}\)
现在假设在 x 点上的球的集合为 S' ,那么我们要把 S' 拆成若干个集合走不同的边到后面的点。
拆完 S' 之后把这些集合和 S 代表的集合 merge 起来,相当于现在有若干个集合,每个集合代表一条边,每条边定一个 [x+1,n] 的终点。
显然可以枚举一部分边连到 x+1 ,然后转移到状态 \(f_{x+1,T}\) , T 是剩下集合对应的状态。
这样得到了一个指数级暴力做法,考虑如何优化。
首先发现转移系数与点的标号无关,因此可以用整数拆分来状态,转移时乘上无标号球转有标号球的系数。
然后就是从 x 到 x+1 的转移的两步可以分开转移,因为第一步转完之后一定是一个 K 的拆分。
这样写就能过了。
code


Comet OJ - Contest #16 小 C 的可重集

先在读入的时候把每个数的出现位置的集合给记下来。
考虑从 1~n 依次确定每个数出现几次,假设当前枚举到数字 x ,考虑二分 x 的出现次数,然后询问比当前序列小的序列个数。
考虑根据 x 出现的位置集合来进行更新,发现对于左端点在 \([pos_{i-1}+1,pos_i]\) 的区间, x 对右端点的下界限制是相同的。
于是考虑对于每个左端点维护右端点的下界相关的信息,容易发现每一轮做下来之后这个下界都是单调不降的,所以每次对下界的更新可以用线段树上二分分界点后区间覆盖解决。
但这样做会漏算一些可行区间,比如现在枚举的序列是 \(1,2,2,3,3,3\) ,我们会漏算掉 \(1,2,2,2,3,3,4\) ,考虑怎么 fix 这个算法。
假设当前枚举的 x 的个数是 y ,那么当左端点在 \(pos_{i-1}+1,pos_i\) 的时候右端点只要 \(\ge pos_{i+y}\) 就一定是合法的(即不用考虑比 x 大的数有几个),于是我们对每个点可以维护出一个其右端点下界的上界(有点绕,慢慢理)。
然后分类讨论维护这个玩意儿就行了。 我调了一年,不知道是因为我菜还是因为细节真的多
以为写了个复杂度 \(O(n\log n)\) 的,然后写这篇博客的时候仔细算了一下发现好像是 \(O(n\log^2n)\) 的...
code

posted @ 2020-02-23 12:21  soroboruo  阅读(498)  评论(0)    收藏  举报