数数的群星闪耀时
科技博客里都有,这里主要是个杂题乱做。
常用简单技巧:
- 多条件至少满足一个直接容斥。
- 至少和恰好直接二项式反演。
- 组合意义,组合意义。
- 生成函数直接上。
- 别组合魔怔了,可以 dp。
- 对于一种情况 \(A\) 可以推出一个 \(B\),要求对不同的 \(B\) 进行计数,这个可以对于每个 \(B\) 找到一个与它唯一对应的 \(A\),然后对这些 \(A\) 计数。
- 如果可以拆成几个无影响的部分,可以先每个部分算然后组合数合并。
ABC285Ex *3192 \(\color{blue}\bigstar\)
显然每个 \(p_i\),相当于把 \(E_i\) 拆成若干个奇数和偶数放到 \(n\) 个数上,要求每个数至少分到一个奇数。
简单 dp 是直接设 \(f_{i,j}\) 表示前 \(i\) 个 \(E_i\),已经有 \(j\) 个数分配到了奇数的方案数,然后直接暴力枚举选多少个奇数以及怎么放,复杂度 \(O(n^4)\),code。放的方法就是先放一堆 \(1\),然后剩下有一堆 \(2\) 插板法乱放。
容斥一下,枚举一下有多少个数是完全平方数,得到:
复杂度 \(O(n^3)\),code
后面那两个东西中含有一个 \(2p\),比较难搞,上生成函数。
可以发现后面那个东西已经和 \(j\) 无关了,因此可以暴力求出 \(\dfrac{(1+x)^{n-i}}{(1+x^2)^n}\) 然后算 \(K\) 个点值即可。
这个东西相当于每次乘一个 \((1+x)\),单次乘复杂度 \(O(n)\),因此直接暴力做即可,复杂度 \(O(n^2)\)。
ABC284G *2218 \(\color{green}\bigstar\)
显然答案算的是连成一个基环树之后每个点走到一个环的步数。
直接拆贡献,考虑枚举链的长度以及环的大小。
由于读入模数,所以组合数显然要扔掉。
化简一下,变成
变成了一个只和 \(i+j\) 有关的式子,\(\dfrac{n!}{(n-i-j)!}\) 相当于是一个后缀积,因此直接考虑每个 \(i+j\) 的贡献就可以做到 \(O(n)\)。
LNR#2D1T3 \(\color{Gold}\bigstar\)
只会 \(O(n^2)\) dp,这个 dp 还是比较套路,设 \(f_{i,j}\) 表示前 \(i\) 个数已经填了 \(1\) 到 \(i\) 的排列,第 \(i\) 个数填了 \(j\) 的方案数,加一个就相当于是插入一个位置即可。
转移就是 <
就后缀和,>
就前缀和。
这个东西不太能优化,寄。
想想能不能容斥,如果直接令一些位置不合法,不太可做。
一个很妙的是,如果把 >
这些位置改成没有限制,那么相当于是一堆递增的序列,假设这些序列长度分别为 \(a_i\),那么总方案数就是
那么,我们直接对于所有 >
进行容斥,钦定一些位置强制改成 <
,剩下位置随意,这样方案数好算。
直接 dp,设 \(f_i\) 表示第 \(i\) 个位置是 >
,前 \(i\) 个的方案数,为了方便,我们只算 \(\frac{1}{\prod (a_i)!}\) 部分,上面的最后乘上。
枚举上一个 >
的位置,可以得到
\(s_i\) 是 >
的前缀和。
转移需要满足 \(i,j\) 都是 >
。暴力做 \(O(n^2)\)。
发现后面是一个卷积形式,直接分治 FFT 即可,复杂度 \(O(n\log^2 n)\)。
LNR#2D2T2 \(\color{blue}\bigstar\)
可以发现 \(p\) 很小,就可以用 Lucas 定理,已知生成函数,要找到他的组合表达式。
可以发现中间一坨组合数,去模 \(p\) 要不等于 \(0\),容易想到对 \(m\) 转成 \(p\) 进制,那么每一位上都必须满足 \(b_i\) 之和等于 \(m\),因此可以每一位单独考虑。
因此我们可以先预处理一下 \(<p\) 的幂次,这个部分是 \(O(n^2p^2)\),然后进行数位 dp,从高到低一次使得 \(\sum b_i=m,\sum ib_i=k\) 成立,又因为 \(a^p\bmod p=a\),所以后面的贡献与数位无关,直接做即可。
总复杂度 \(O(n^2p^2+Tn^2\log_p m)\)。
loj2320 \(\color{Gold}\bigstar\)
先枚举每个连通块度数写式子:
这个式子就是说,每次删除一个连通块记录 prufer 序列,那么贡献就是后面那个东西了,因为在 prufer 中出现 \(d_i-1\) 次,又删除时一次。
会发现这个东西很阴间的一点是后面并不是关于 \(d_i\) 独立的 \(n\) 个东西乘起来,因为有个 \(\sum d_i^m\) 不好搞。我们把它和前面的 \(\prod d_i^m\) 大力展开,这步想不到。
然后会惊人的发现,\(i\) 可以放到外面来。
右边变成了比较常规的形式,直接生成函数一波。
这样的好处是分成两个部分可以分别求,然后卷起来。
最右边那个直接 \(n\) 个多项式乘起来不太好搞,一个想法是求封闭形式,可以发现其本质是指数相加,转化为加法。
大概可以把 \((d+1)^m\) 二项式暴力展开然后得到封闭形式,不过没什么用。
但是好像可以直接展开成斯特林数做,但是这样复杂度会带上 \(m\)。
设 \(C(x)=\frac{A(x)}{B(x)}\),那么可以得到
然后这个东西只要保留前 \(n-2\) 项即可,所以先求 \(C(x)\) 就可以算了。
接下来要算的是 \(\sum_{i=1}^n a_i^j\)。
设一下他的生成函数,要求的就是 \(\sum_{i=1}^n \frac{1}{1-a_ix}\),直接分治 FFT。
然后 \(\sum_{i=1}^n \ln B(a_ix)\) 和 \(C\) 差不多的算就好了。
总复杂度 \((n\log^2 n)\)。
loj3120 \(\color{blue}\bigstar\)
考虑最后总共的组成一对一对的个数就是 \(\frac{n-cnt}{2}\),\(cnt\) 指选奇数个的元素。
可以直接去算 \((\frac{e^x+e^{-x}}{2})^{D-i}(\frac{e^{x}-e^{-x}}{2})^i\),但是比较难搞,考虑二项式反演一下,变成钦定 \(i\) 个选偶数,这样式子变成 \((\frac{e^x+e^{-x}}{2})^ie^{(D-i)x}\)。
后面那个东西卷积,然后二项式反演回来即可。
AGC061C *2697 \(\color{blue}\bigstar\)
考虑对于一种人的排列,如何找到一个合法的方式?
一个人可以在一个区间的左端点或者右端点标记,那么贪心显然是尽量填左端点,左端点填不了再填右端点,容易发现这样就唯一对应了,我们只需要数这样放的方式即可。
在观察一下这种方案的性质,可以发现对于一个区间,如果它选了右端点而没有选择左端点,并且区间中间没有任何人选在这里,那么这样的方案一定不合法,否则一定合法,因为所有端点都不能选到更前面。
可以发现每个区间都选左端点或者右端点,只有选右端点的区间可能不合法,所以我们先选若干个区间让他们选右端点,然后剩余的都只能填左端点,在考虑是否合法。
区间按左端点排序,从由向左考虑,对于每个区间,如果选择了右端点,考虑在它区间中被选的点是左端点还是右端点,如果是左端点那么就是它右边的区间,否则是左边的区间。
设 \(f_{i,0/1}\) 表示 \(i\) 强制选右端点,这个区间是否在后面已经合法,因为如果不合法就需要左边的去满足。
然后考虑对于 \(i\) 去枚举后面的一个 \(j\)。
-
如果 \(i,j\) 没有交,那么 \(j\) 对 \(i\) 无影响,直接转移。
-
否则,\(j\) 选左端点时能满足 \(i\),\(i\) 一定能满足 \(j\),可以发现转移到 \(f_{i,0}\) 需要满足所有这样的 \(j\) 都选了右端点,因此找到最右边的 \(j\) 直接转移到 \(f_{i,0}\),其他转移到 \(f_{i,1}\) 即可。
加个前缀和优化就可以 \(O(n)\)。
赛时过了这题直接原地起飞,可惜 unr,但是把 Lianyouchang 送上 3Dan 了。
AGC021E *3944 \(\color{Gold}\bigstar\)
依然考虑去对应,对于一个 RB
方案,先考虑 \(n=1\) 的情况,如果 \(R>B\),那么必定合法,\(R<B\) 必定不合法,\(R=B\) 的情况比较阴间,不太会。
考虑还需要去满足 \(n-1\) 个其他的,那么考虑让一个东西合法最优秀的方案就是给一个 \(R\) 以及它后面的一个 \(B\),这样 \(R-B\) 不变。
如果这样的东西全部取完了,把 \(R\) 想象成左括号,\(B\) 是右括号,那么显然是前面全是 \(B\),后面全是 \(R\)。
如果还有没满足的,那么就只能直接给一个 \(R\) 去满足。
这样放完后,剩下的全部给第一个即可。
但是此时第一个吃的球可能 \(R=B\),非常难以判断,因此看题解。
如果 \(R=B\) 且合法,说明最后一个一定是 \(B\),直接令 \(B-1\),这样满足 \(R>B\),一定合法。
因此只要强制第一个一定是 \(R>B\) 的,数方案数即可。
枚举一下 \(R\) 放即可,卡特兰数算一下就好了。
AGC021F *4145 \(\color{blue}\bigstar\)
这个题就相对简单了。
依然考虑去对应,对于一种 \(A,B,C\),将所有能涂黑的全部都涂黑,然后数方案。
相当于每一列选了一个区间,然后每一行要选择一个点,不能是区间端点,只需要考虑 dp 顺序即可,是从上往下还是从左往右。
从左往右 dp,这样会确定一些行已经选过了点,然后再不断确定新的点。
设 \(f_{i,j}\) 表示已经有了 \(i\) 列,其中有 \(j\) 行已经选过点的方案数,然后考虑去加一行。
如果加一行不选点,那么考虑区间就可以乱选,系数是 \(1+j+\binom{j}{2}\)。
否则需要选,比如 \(f_{i,j}\) 去转移 \(f_{i+1,k}\),相当于 \(k\) 个里面选择 \(j\) 个表示已经选过的东西,然后又要选一个区间包含所有没选过的东西的方案。
令 \(x=k-j,y=j\),也就是说直接插板,然后 \(y\) 的最左边和最右边两端要各选一个点来放区间。
这是经典套路,直接多两个球,多两个板即可,最后得到 \(\binom{x+y+2}{x+2}=\binom{k+2}{j}\)。
转移方程就是
NTT 一下,复杂度 \(O(nm\log n)\)。
CF1654H *3500 \(\color{blue}\bigstar\)
挺有趣的。
考虑一下最后的排列长什么样子,令 \(p_{i-1} > p_i < p_{i+1}\) 的位置是关键点,那么可以发现两个关键点中间一定是一个先单调增然后单调减的结构,那么不合法的 \([l,r]\) 只有可能落在两个关键点上,那么这个限制相当于说明关键点的值必须是先单调减再单调增的。
那么中间最低的那个点一定是 \(1\),把序列分成了两半。
假设前面 \(i\) 个位置,\(i\) 的地方填 \(1\),前面总共填了长度为 \(i\) 的排列的方案数是 \(f_i\),\(i\) 后面的方案数是 \(g_i\),那么答案就是:
然后考虑 \(f_i\) 咋求。
一个简单的想法是直接去枚举上一个关键点,但是发现这样需要枚举位置和大小,很浪费。
换一个角度,\(2\) 可以放在哪里,容易发现要么放在 \(i-1\),要么放在上一个关键点的位置。
因此
\(g\) 的转移也类似。
然后这个东西显然可以用分治 FFT 优化。
但是题目规定了一个前缀的大小关系。
对于 \(f\) 的转移,相当于是限制了上一个关键点的位置,可以暴力转移 \(O(nm)\)。
对于 \(g\) 的转移,也是限制关键点的位置,这里限制的位置可能是个区间,因此需要组合数前缀和预处理一下,也是 \(O(nm)\)。
与 \(m\) 无关的部分可以分治 FFT。
总复杂度 \(O(n(m+\log^2n))\)。