想题记录
wtcqwq
2.3~2.6
Todo List
除了省选计划题单、模拟赛补题和刷 AGC 以外。
- LGV 引理和线性代数;
- USACO Jan 的 G 和 P 组想一想学一学做一做。
随记
2.4。只有刺痛自己的时候才能认知自我啊...
2.4。好冷。机房里已经空无一人了。真希望确实是 “高处不胜寒” 啊。
2.5。hey bro。u can do this
。感觉到了暖流一般。
P5303
info
紫。完全自己想的。
tag:math,dp
思考路径
一个显然的容斥是,两块小砖不能连在一起的约束不方便 dp 和数学,我们可以将这部分贡献容斥掉。
现在问题变成了 \((n-1)\) 块 \(2\times n\) 的砖和两块小砖有多少种拼法,减去斐波那契数列。
前面这个问题可以 dp 了。
\(dp_{i,j,k}\) 表示考虑到第 \(i\) 列,第 \(i\) 列已经放了 \(j\) 块转,用了 \(k\) 块小砖。显然 \(0\le j<2,0\le k\le 2\)
- 如果 \(j=0\)
- 可以直接放一块竖大砖,\(j,k\) 不变,\(i\) 变大 \(1\);
- 可以放一块小砖,\(j,k\) 变大 \(1\),\(i\) 不变;
- 可以直接放两块竖着的大砖,\(j,k\) 不变,\(i\) 变大 \(2\);
- 可以直接放一块竖着的大砖和两块小砖,\(j\) 不变,\(k\) 增大 \(2\),\(i\) 变大 \(2\);
- 如果 \(j=1\)
- 可以放一块横大砖,\(j,k\) 不变,\(i\) 变大 \(1\);
- 可以放一块小砖,\(i\) 变大 \(1\),\(j\) 置为 \(0\),\(k\) 变大 \(1\)。
直接转移即可吧。
这样写太麻烦了。
考虑两个零碎的块之间 \(2\times m\) 的长方形。一定只有一种拼法(而且不会出现竖着的占着一列的)
前面后面的,都是 fib。
式子等价于
设 \(S\) 表示 \(F\) 的前缀和数组,则原式转化为
又,\(S_n=F_{n+2}-1\)。
Proof:\(S_n=F_{n+2}-1\)。
\(F_3=F_1+F_2\)
\(F_4=F_2+F_3\)
\(F_5=F_3+F_4\)
\(\cdots\)
\(F_{n+2}=F_{n+1}+F_n\)。
所以 \(S_{n+2}-2=S_{n+1}+S_n-1\)。
也就是 \(S_{n+2}-1=S_{n+1}+S_n\)
\(S_n+1=S_{n+2}-S_{n+1}=F_{n+2}\)。
\(S_n=F_{n+2}-1\)。
所以,原始转化为
也就是
后面那一坨再用求和公式,
现在设 \(G_n=\sum^{n}_{i=0} F_i\times F_{n-i}\)。
可以推一手发现,\(G_n=G_{n-1}+G_{n-2}+F_n\)。
直接矩阵快速幂即可。
代码
submission
总结
- 硬去 dp 是毫无价值的,这对正解启发有限。
- 意识到两个小砖的特殊性,考虑钦定这两个砖的位置。
- 斐波那契数列的性质、快速求解方法和 \(2\times n\) 砖块的价值。
P8321
info
紫。第一步就卡了。
tag:dp
思考路径
25 分部分分是好拿的。暴力略。
特殊性质:如果 \(A_n\ge \max^n_{i=1}(B_i)\) 的话,任何的 \(\min\) 都一定会取到 \(B_i\) 身上。这样的话,一共 \(n!\) 个排列,每个的代价都是 \(\prod b_i\)。
满分就不会了。
题解
我们需要把问题抽离出排列来看。考虑将 \((i,p_i)\) 当作一个二元组。排列等价于二元组的匹配关系。
问题转化成,一个匹配 \(\pi\) 的权值是 \(\prod^n_{i=1} \min(a_i,b_{p_i})\)。求所有匹配的权值和。
接下来考虑怎么刻画 \(\min\),一个典型 trick 是排序后,将 \(\min\) 化作下标较大的那个。
我们直接把 \(a,b\) 两个序列合并为 \(c\)。设定 \(dp_{i,j}\) 表示考虑到第 \(i\) 个,已经匹配了 \(j\) 对的总权值。
考虑当前的这一位,我们有两种选择:
-
将它进行匹配:
有 \(g-(j-1)\) 个可供匹配的(其中 \(g\) 是异色的个数)。
前面的总代价是 \(f_{i-1,j-1}\)。
所以 \(f_{i,j}\leftarrow f_{i-1,j-1}\times c_i\times (g-j+1)\)。
-
不将它进行匹配:
代价就是 \(f_{i-1,j}\)。
转移式就有了。计算 \(g\) 可以直接前缀和。时间复杂度 \(O(n^2)\)。
代码
现在是 14:02,我认为我可以在 15min 里写完。
现在是 14:09,我过了。submission。
总结
- 排列问题可以转化成匹配问题。下标和值是常见的二元组,可以转化成匹配或者平面直角坐标系下的一个点。
- 匹配问题可以染色后合并在一起。\(\min\) 的典型转化包括排序后按扫描线的先后处理或者 \(\min-\max\) 容斥。
P5239
info
绿。
tag:数学
思考路径
没懂这个题有啥价值。直接做即可。
时间复杂度 \(O(n^2+q)\)。
代码
现在是 14:14,我觉得我可以在 10min 里写完。
现在是 14:19,我过了。submission。
总结
这是组合数和组合数二位前缀和的板子。
c[0][0]=1;
for(ll i=1;i<=1000;i++){c[i][0]=1;for(ll j=1;j<=1000;j++){if(i>=j) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+c[i][j];dp[i][j]%=mod; (dp[i][j]+=mod)%=mod;}
}
P8576
info
紫。
tag:分块,数学,数据结构
思考路径
发现这个很恶俗的式子一定不是硬做,我们来化简一手。
原式是
写成阶乘相除的形式:
发现 \(\sum^i_{j=l} a_j-a_i\) 太过分,写成阳间形式 \(\sum^{i-1}_{j=l} a_j\)
则原式变成了
发现分母中的 \((\sum^{i-1}_{j=l} a_j)!\) 会与后一项的分子约分掉。
最后剩下的只有
上面是区间和,下面是区间积。
考虑第一个修改操作怎么做。可以分块。
每一块里维护值出现了几次,以及某个值现在实际代表什么(可以维护 \(\sqrt n\) 个并查集)
不知道 511MB 的价值是什么。
代码
现在是 14:48,我认为我可以在 40min 里写完。
现在是 15:53,我要调不动了。
现在是 16:02,我过了。submission
总结
- 恶臭式子需要推一步,转化成简单的区间加区间阶乘积的问题。
- 分块书写的时候,不妨使用 remake 重构,来代替恶臭的散块处理过程。
P3773
info
紫。
tag:数学、Lucas定理、枚举子集、dp
思考路径
考虑
等价于
考虑
的充要条件。带入 Lucas 定理发现:
发现这本质上是一个二进制拆开的过程,且要求每一个
此时,只能是
所以 \(y\) 的每一位都是 \(x\) 的子集。
综上
枚举子集直接做 dp 即可。时间复杂度 \(O(3^{\log \max a_i})\)。
代码
现在是 16:26,我认为我可以在 10min 里写完。
现在是 16:34,我写完了。submission。
CF1002D
info
蓝。
tag:最短路
思考路径
考虑只要两个棋子在某一个一样的点上,这个点的相邻点两个图存在交集,只要走过去走回来,这样循环往复,则代价永远是 \(0\)。
我们要考虑怎么让两个棋子在一个一样的点上。将 \((v_1,v_2)\) 这样的二元组状态设定成一个点。
则边就是 \(v_1\) 的邻域中点 \(u_1\) 和 \(v_2\) 的邻域中点 \(u_2\),从 \((v_1,v_2)\) 花费 \(|u_1-u_2|\) 的代价走到 \((u_1,u_2)\)。
然后只要一个点,满足这个点在两个图上的邻域有交集,设定为好点。
答案就是
dijkstra 堆优化求即可。考虑新图上点是 \(O(n^2)\) 级别个(\(10^6\) 个),边数则是 \(\sum dgr_{u_1}\times dgr_{u_2}\),这和 \(m_1\times m_2\) 同阶,时间复杂度是对的。
代码
我认为 20min。现在是 16:57
现在是 17:16。submission。
2.4 模拟赛 A
info
紫。
tag:dp、人类智慧
下文约定 \(t\) 经过排序。
思考路径
一开始猜测,每次回来的肯定是在对岸的最小的。这个应该是对的。
但是这对解决问题没有价值。
然后我猜测,在对岸的一定构成一个区间。这玩意非常好 hack。
发现样例就不满足条件:
4
1 2 5 10
可能分裂成头尾两个区间。
然后继续猜测,将 \(t\) clone 一份,然后对岸的一定构成一个区间。
然后我就敲出了把 \([l,r]\) 视作一种状态跑最短路的代码。
然后这个东西也假了。因为复制一边的话,假设第一个状态 \([l,r]\) 满足 \(l<n,r>n\),那最小值就不在区间两端。
把这个东西拆开的话,又变成不是一个区间了。
来自 klc 的 hack 是
13 4
1 1 1 1 1 10 10 10 10 10 10 10 10
然后我就不会做了。
btw. 发现 \(c=2\) 是典题。每次要么最小的两个去,要么最大的两个去,要么小带大去。稍微贪一手就行了。
可以得 20 分。这就是今早的全部了。
我认为我可以在 5min 左右写完,差不多也就是 5min。
if(c==2){ll ans=0; while(n>3){ans+=min(t[1]*2+t[n]+t[n-1],t[1]+t[2]*2+t[n]);n-=2;}if(n==2) ans+=t[2];if(n==3) ans+=t[1]+t[2]+t[3];printf("%lld",ans);return 0;
}
题解
考虑我们关心的只有,每次送过去的人次里,有几个呆在那里不动了(记为 \(a\)),有几人次回来了(记为 \(b\)),一次这样的操作构成二元组 \((a_i,b_i)\)。
这样的东西构成 \((a_1,b_1),(a_2,b_2),\cdots,(a_k,b_k)\)。
考虑这样的话我们需要送 \(k-1\) 次火把,也就是 \(\sum_{i=1}^k b_k=k-1\),最终态的话,显然 \(\sum^k_{i=1} a_i=n\)。
可以理解为
设定一个二元组的权值是 \((b_k-1)\)。
假设放了一个权值为 \(x\) 的二元组,满足 \(x>0\),在后面塞 \(x\) 个权值为 \(-1\) 的二元组。最后再塞一个就行了。
发现这样的费用就是
对着这个式子 dp 即可。
还有一种可能是,选了小于 \(m\) 个人,最后都回来了(如果选够 \(m\) 个人,可能用不着,使得这一次操作代价变大)
这个东西我们单独处理 \(f\)。
然后 \(dp_{i,j}\) 的话,相当于维护 \(\sum a=i,\sum (b_i-1)=j\) 的值,把 \(dp\) 和 \(f\) 的结果拼起来即可。
注意到 \(j\le \frac n m\) 然后时间复杂度就是 \(O(n^2)\) 的了。
所以出题人不给暴力/状压的部分分是什么素质。\(n\leq 100\) 对于正解没有提示意义啊。这道题也没有 \(O(n^2\log n)\) 的做法啊,那 \(O(n^2)\) 你开到 \(n\le 10^4\) 是纯粹为了迷惑选手吗。
代码
现在是 14:32,我认为我可以在 25min 写完。
现在是 14:43,我过了。submission。
总结
-
题目不好做的时候,考虑能不能用二元组/二元组集合来表示。并且给这样的意象加上代价。这会极大方便我们 dp。
-
考虑到这种题目时,多手玩几组数据,争取可以用少量的几种操作来描述一个最优化问题。
P8594
info
紫。
tag:dp、矩阵快速幂(only bf)、组合数
思考路径
有一个显然的 \(O(n^2k)\) 的暴力。\(dp_{i,j,k}\) 表示第一行填了 \(i\) 个,第二行填了 \(j\) 个,一共花了 \(k\) 个矩形的方案数。
然后发现这个东西很不优。因为每一列一共就那么几种情况:
-
要么竖着填了一个。
-
横着放的话,
两行其实是独立的,每一行可以考虑:前一个缝隙是断开的还是没有断开。
显然如果前一列是竖着填的话,就只能是断开的了。其它的可以直接做。
这样的话就可以获得 50 分。我认为我可以在 10min 左右写完。
现在是 15:15,我拿到了 50 分。submission。
然后接下来的 \(k\) 比较小的,应该套一个矩阵快速幂就行了吧。但是不是很 practical 不写了。
题解
发现竖着的 \(k\) 个方块其实就是将整个长度为 \(n\) 的板拆成 \(k+1\) 份,可空,假设每一份分别是 \(a_i\)。则 \(\sum a_i=n\)。
然后我们现在来考虑下 \(2\times a_i\) 用 \(b\) 个板子,不允许竖板的答案:
这个时候上下两行就独立了。我们假设第一行花了 \(i\) 个板子。那么第二行就花了 \(b-i\) 个板子。
这个时候我们发现,上下就都变成了隔板法了。
也就是
\[\sum ^{b}_{i=0} \binom{a-1}{i-1} \times \binom{a-1}{b-i-1} \]根据范德蒙德卷积:
\[\sum^k_{i=0} \binom n i \times \binom{m}{k-i} = \binom{n+m}{k} \]上面那个式子等价于
\[\binom{2a-2}{b-2} \]
然后考虑如果我们放了 \(j\) 个竖着的板,剩下的 \(n-j\) 排被分成了 \(i\) 段。分这一步的方案数是 \(\binom {n-j-1}{i-1}\)。
然后考虑这就转化成了前面的问题的子问题,假设存在若干个 \((a_i,b_i)\) 来求解上面的问题,则
这个东西组合意义可以表示为从 \(\sum 2a_l-2\) 中选取 \(\sum b_l-2\) 个的方案数。把上面这些全部乘起来就可以了。
也就是
考虑到 \(n=k\) 的时候,可以每一列都竖,加上即可。
时间复杂度 \(O(k^2)\),有预处理的复杂度。
现在是 15:29,我认为我 20min 写的完。
现在是 15:52,我过了。submission。
总结
- 开 \(4\times 10^7\) 数组的时候要当心,爆了一次内存。不能全局开 long long
- 如果题目不会,不妨先把不容易处理的部分删掉。本题中竖着的类似分隔符的小方块非常碍事。删掉以后答案可以轻巧地用组合数表达出来。
- 如果上下指标求和有价值的话,考虑范德蒙德卷积。
- 组合题要考虑一些复杂式子的组合意义,毕竟组合公式纷繁复杂且未必看得出来,而组合公式都可以用组合意义解释。
P8367
info
黑。
tag:动态规划、组合数、数学
思考路径
假设 \(c\) 是 \(a\) 的前缀和数组,\(d\) 是 \(b\) 的前缀和数组,则答案就是
考虑 \(a\) 知道了,\(c\) 也就知道了。考虑 \(\sum b=S\),等价于 \(d_n=S\)。
所有可能的 \(b\) 和所有不下降序列 \(d\) 构成双射。
设 \(dp_{i,j}\) 表示考虑到 \(d\) 的第 \(i\) 项,\(d_{i}=j\) 的所有 \(d\) 的和。
枚举 \(d_{i-1}\) 来转移,朴素实现的话时间复杂度是 \(O(nS^2)\),只能期望获得 20 分。
显然,
可以前缀和优化,时间复杂度降到 \(O(nS)\),期望获得 40 分。足够优秀的常数优化的话不知道能不能 60。
现在是 16:21,我觉得我要花 20min。
现在是 16:38,我拿到了 40 分。submission。
题解
先考虑一对 \((i,d_i)\) 出现的条件。一个 \((i,d_i)\) 出现当且仅当前 \(i\) 个 \(b\) 加起来是 \(d_i\),后 \(n-i\) 个 \(b\) 加起来是 \(S-d_i\)。
期望具有线性性,可以直接加起来。
直接算的话,时间复杂度还是 \(O(nS)\) 的,还是 40 分。
然后我们推一波式子:
设
发现:
带入可得
也就是
发现就是
我们只要每次把 \(i,k\) 移动 \(1\),然后维护答案即可。
移动 \(k\) 显而易见,多加一项就行了。
移动 \(i\) 牵扯太多,不好动,考虑换一种角度来理解。
\(f(n,m,i,k)\) 的本质是:求长度为 \(n\) 的数列 \(a\) 的个数,使得 \(\sum a=m\),\(\sum^i_{j=1} a_j\le k\)。
我们不妨考虑第 \(k+1\) 个在哪里:
然后莫队一般地转移即可。因为 \(a\) 的前缀和数组 \(c\) 单调不降,所以这样的转移不会超过 \(n+m\) 次。
代码
现在是 16:57,我觉得我可以在 40min 内写出来。
现在是 17:01,我发现没我想的这么简单。细节好像爆多。
我写不动了。明天再说吧。
总结
我有很多想说的,但是这里写不下。
P4562
info
蓝。
tag:期望、数学、数论
思考路径
考虑有若干个会通风报信的点,且一定需要它们通风报信(因为它不是任何别人的倍数)。
称这样的点为关键点。假设这样的点有 \(k\) 个。
则恰好在最后一个关键点之后的概率是
又,有 \(n-k\) 个非关键点独立取值。
所以,最后一个关键点排名的期望就是:
乘上所有的 \(n!\) 个排列:
代码
现在是 17:24,我觉得我可以在 3min 以内写完代码。
现在是 17:27,我过了。submission。
总结
- 在一个排列里,有若干个关键点(关键点也是随机生成的),则指定一个点在关键点的分段中出现的概率均等。
- 用组合数不太好解释的,不妨考虑概率和期望。
P11676
info
紫。
tag:树、dfs 序、区间 dp
这有紫???
思考路径
先看 Subtask 1,在 Subtask 1 的条件下,所有边都不在,只能加边。
\(dp_{l,r}\) 表示使 \(l\to r\) 构成一个可能的 dfs 子段的最小总代价。
这是一个区间 dp,考虑如何合并。如果 \(l\) 可以走到 \(k\),\(k+1\) 可以走到 \(r\)。
那么只要 \(l\) 有一条连到 \(k+1\) 的边,\(l\) 就可以走到 \(r\) 了。
总结一下,
然后来看 Subtask 2,这个时候就要考虑删边了。
同样地,考虑如何合并 \(dp_{l,k}\) 和 \(dp_{k+1,r}\)。
如果 \((l+1)\sim k\) 有边连到 \((k+1)\sim r\) 那也不行。这些边都要删掉。
所以设
则,
朴素地求 \(G_{l,k,r}\) 是 \(O(n^2)\) 的,总复杂度 \(O(n^5)\),可以通过 Subtask 2;
二位前缀和预处理一手,就是 \(O(n^3)\) 的了,可以获得满分。虽然不知道 \(n^3\) 开 \(n=750\) 是犯了什么病。
代码
现在是 17:55,我觉得我可以在 10min 里写完。
现在是 18:01,我过了。submission。
总结
- 树上的 dfs 序问题未必指向树形 dp,可以理解为一个下标到另一个下标不可抗力的联通关系,然后用区间 dp 去做。
P6657
info
紫。lgv 引理的模板题。
tag:lgv 引理、组合数
题解
什么是 lgv 引理?
设矩阵\[M=\begin{pmatrix} e(a_1,b_1)&e(a_1,b_2)&\cdots&e(a_1,b_n)\\ e(a_2,b_1)&e(a_2,b_2)&\cdots&e(a_2,b_n)\\ \vdots&\vdots&\ddots& \vdots\\ e(a_n,b_1)&e(a_n,b_2)&\cdots&e(a_n,b_n) \end{pmatrix} \]则有
\[\det(M)=\sum_{S:A\to B} (-1)^{\sigma(S)} \prod w(S_i) \]
考虑这道题是一个网格图,考虑到 \(a_1\le a_2\leq \cdots \leq a_m,b_1\leq b_2\leq \cdots \le b_m\)。
显然只能按序匹配,也就是 \(a_i\to b_i\),要不然一定会有交。
所以 \(P_i=i\),也就是
将 \(\det M\) 计算出来即可。
代码
submission
CF348D
info
紫。*2500
tag:lgv 引理
思考路径
考虑到两个人第一步和最后一步肯定不能是同一个点,要不然就有交了。
所以我们不妨拆成 \((1,2),(2,1)\) 两个起点和 \((n,m-1)\) 和 \((n-1,m)\) 两个终点。
要求路径不交,套路地套用 lgv 引理。
可能的 \(S\) 有两种:\((1,2) \to (n,m-1),(2,1)\to (n-1,m)\),此时贡献是正的。
\((1,2)\to (n-1,m),(2,1) \to (n,m-1)\),此时贡献是负的。
\(M\) 的构造显然:
直接用 dp 推一遍这四个的答案即可。
代码
现在是 9:53,我觉得 20min。
现在是 10:16,submission。
总结
- 如果 lgv 引理的题目中,所有点的起点和终点都相同,但起点和终点不计入”重合“,可以把所有第一步和最后一步枚举出来考虑。
- 计算 \(e\) 方式多样,套路地考虑棋盘格上 dp。
P7736
info
紫。
tag:lgv 引理、dp
思考路径
”偶数个交点的路径比奇数个交点的路径多多少个“ 也就是 偶数个交点的路径 - 奇数个教练的路径。
发现这和 lgv 引理中 \((-1)^k\) 相似。
考虑怎么把 偶数、奇数 和 终点起点的对应关系的逆序对个数联系起来。
考虑 \(a_i>a_j \and b_i<b_j\) 的时候,一定会产生奇数个交点。反之一定会产生偶数个交点。
这个关系就是逆序对的个数的奇偶性。
Proof:\(a_i>a_j\and b_i<b_j\) 时一定会产生奇数个交点。
假设 \(a_i\) 走到 \(b_i\) 的路径是 \(S_i\),\(a_j\) 走到 \(b_j\) 的路径则是 \(S_j\)。
考虑如果 \(k\) 和 \(k+1\) 之间产生了一个交点,则:
- 如果 \(S_{i,k}<S_{j,k}\),则 \(S_{i,k+1}>S_{j,k+1}\);
- 如果 \(S_{i,k}>S_{j,k}\),则 \(S_{i,k+1}<S_{j,k+1}\)。
显然 \(a_i=S_{i,0},b_i=S_{i,K+1}\)。
如果产生了偶数个交点,相邻的两次相交后,大小关系不变。显然 \([a_i>a_j]=[b_i>b_j]\),矛盾。
所以一定是奇数个交点。
代码
现在是 10:38,我觉得我能在 20min 内写完。
现在是 10:44,submission。
总结
- 两条曲线的交点个数的奇偶性和曲线起点终点的大小关系是否相同有关:
- 如果曲线开头和结尾的大小关系相反,则有奇数次相交;
- 相同,则有偶数次相交。
- 在路径不交问题上,如果出现了【A】比【B】多,更应该警惕。这可能恰好对应了 lgv 引理的 \((-1)^k\)。
ABC216H
info
黑。
tag:lgv 引理、容斥原理、状态压缩 dp。
思考路径
不难发现这个概率是假的,直接算方案数,然后除以 \(2^{nm}\) 即可。
不难发现这个 \(\frac 1 2\) 的概率也是假的,乘上 \(2^{nm}\) 以后,在 \(n\) 秒的时间走 \(k\) 个的方案数就是 \(\binom n k\) 即可。
几个和前面看到的 lgv 引理不太一样的点:
- 终点集合不确定
- \(k\) 很小。
发现这道题仍然是网格图:如果我们知道了终点集合 \(\{T\}\)。那么 \(\{S\}\) 和 \(\{T\}\) 一定从小到大一一对应,要不然一定有交。
所以我们可以从小到大钦定 \(T\) 选不选,然后尝试对着 \(T\) 匹配 \(S\)。但是怎么设计 dp 状态呢。\(dp\) 状态还要能体现出逆序对的个数。
一个自然的 dp 思路是 \(dp_{s,i}\) 表示目前 \(\{S\}\) 和 \(\{T\}\) 已经从小到大匹配成的路径所构成的集合是 \(s\),目前 \(\max \{T\}=i\)。
每一次扔一个新的 \(i+1\) 进去,只要考虑跟谁匹配即可。枚举跟 \(S_j\) 匹配。
然后 \(e\) 是好求的,但是逆序对个数怎么刻画呢。
逆序对个数应该就是 \(S\) 里低 \(j-1\) 位已经匹配好的个数。
直接 dp 应该就行了吧。时间复杂度 \(O(2^k kn)\)。
题解
稍微借鉴了一手怎么初始化。
代码
现在是 10:59,我觉得我能在 20min 里写出来。
现在是 11:25,submission。
总结
- lgv 引理本身需要一个明确的起点集合和终点集合。但是其实对于终点集合,我们只关心它与那个起点相匹配,以及这样的匹配会造成多少个逆序对。
- 如果每一种方案,会造成的决策次数相等(即等概率),则这个概率或者期望就是假的,不妨直接求出方案数,然后统一乘上这个概率。
- 数据规模提示的状态压缩 dp 可以记录是否匹配。
P8863
info
紫。
tag:状态压缩 dp、dp
思考路径
Tc 1~3
\(\sum b_i\bmod 2=1\) 或 \(n=1\) 显然答案都是 \(0\)。输出 \(0\) 可以获得 \(12\) 分。
Tc 4~5
\(n=2\) 的话,如果 \(b_1=b_2\),则输出 \(1\),反之输出 \(0\)。可以获得 \(20\) 分。
Tc 6~8
直接暴力,或者直接把 vector 当作状态,然后记忆化搜索的状压 dp。
类似 \(O(n^{\sum b_i})\) 的复杂度都是可以接受的。可以获得 \(32\) 分。
Tc 9~11
显然 \(b_i=1\)。把哪些位置满足了记录出来当作状态。然后状压 dp。
时间复杂度 \(O(2^n)\)。可以获得 \(44\) 分。
Tc 12~14
发现 \(i,j\) 此时构成了一种匹配关系。
让一个人来找另外一个人。第一个找的人是 \(n-1\) 种方案。
第二个则是 \(n-3\) 种。乘下去即可。可以获得 \(56\) 分。
Tc 15~18
继续考虑怎么状压。
发现对着每个数来 dp 前途有限,考虑对着操作来状压。
发现操作次数固定:\(\sum b_i=16\),一共 \(\frac{\sum b_i}2\) 次操作。我们状压出来每一次操作目前已经固定了 \(\empty,i,(i,j)\) 三种之一。还需要加上 \(n\) 方面:目前考虑到前 \(i\) 个。
状态数大概是 \(O(3^{\frac{\sum b_i}2}n)\) 种。结合获得 \(72\) 分。
Tc 19~20
发现上面这个东西,其实你也不是很关心每一次操作分别是哪个。
记录成集合态,然后记出目前考虑到前 \(i\) 个数,有 \(j\) 次操作已经固定了 \((i,j)\),\(k\) 次操作已经固定了 \(i\)(还没有固定 \(j\))。这样的话时间复杂度就是 \(O((n+\sum b_i)(\sum b_i)^2)\) 的。显然 \(j+k<2\sum b_i\)。发现肯定有一个 \(\frac 14\) 的常数。结合获得 \(80\) 分。
题解
Tc 21~25
发现 \(2j+k = \sum^{i}_{f=0} b_f\)。知道 \(j\) 就知道 \(k\) 了。时间复杂度 \(O((\sum b_i)(n+\sum b_i))\)。
发现实际操作位置只有 \(\frac{\sum b_i}2\) 个,再加上常数小,过了。
代码
现在是 14:19,我认为 20min。
现在是 14:29,submission。
P2260
info
紫。
tag:推式子、整除分块
思考路径
\(n\bmod i=n-\lfloor \frac n i \rfloor\times i\)。
把这个式子拆开,
发现可以容斥。先假设 \(i\) 可以等于 \(j\)。
根据 \(\sum\) 可以调换顺序的性质:
然后前面后面这两个都是一维整除分块。
来想一下 \(i=j\) 怎么做:
拆开来:
四项拆开来:
-
第一项的结果是 \(\min(n,m) nm\)。
-
第二项的结果是 \(n\sum^{\min(n,m)}_{i=1} \lfloor \frac n i\rfloor\),这也是一个一维整除分块。
-
第三项和第二项同理。
-
第四项,也是一个一维整除分块,只要每一块要满足被 \(n\) 除以和被 \(m\) 除以都相等。
考虑到两个的区间分别至多只有 \(\sqrt n\) 个,又满足单调性,所以端点可以按序插入,最多也就是 \(2\sqrt n\) 个区间,不影响数量级。
这时候求和要求的是 \(\sum i^2\),可以采用平方和公式来算。
\[\sum^n_{i=1} i^2=\frac{n(n+1)(2n+1)}{6} \]
代码
现在是 16:07,我认为 30min。
算了。不写了。这东西纯粹精神污染。
CF1278F
info
紫。
是 2.6 模拟赛 C 的弱化版。
tag:推式子、数学、第二类斯特林数
题解
先把题目要求的式子写出来:
其中 \(p=\frac 1 k\)。
下降幂
符号是:\(x^{\underline n}\)。
一些典型性质:
\[x^{\underline{n}}=\frac{x!}{(x-n)!}=\prod^{n-1}_{k=0} (x-k)=\prod^{x}_{k=x-n+1} k \]利用第二类斯特林数将普通幂
\[x^n=\sum_k {n\brace k} x^{\underline k} \]
我们把 \(i^k\) 拆开:
交换一下求和顺序
Lemma 1:
\[\sum^n_{i=0}\binom n i i^{\underline j} = n^{\underline j}\sum^n_{i=0} \binom{n-j}{i-j} \]Proof:
\[\sum^n_{i=0} \binom n i i^{\underline j}=\sum^n_{i=0} \frac{n!}{i!\times (n-i)!} \frac{i!}{(i-j)!} \]右式约分一下:
\[\sum^n_{i=0} \frac{n!}{(n-i)!\times (i-j)!} \]“分母是两个阶乘的积” 提示我们带入组合数的阶乘式:
\[\sum^n_{i=0} \frac{(n-j)!\times n^{\underline j}}{(n-i)!\times (i-j)!} \]也就是
\[n^{\underline j}\sum^n_{i=0} \binom{n-j}{i-j} \]
原式等价于
发现 \(i-j\) 不够优美,用 \(i\) 代替 \(i-j\)。
然后把 \(p_j\) 提到前面来,也就是
二项式定理
\[(a+b)^n=\sum^{n}_{i=0} \binom n i a^i b^{n-i} \]发现上式的第二个和式和这个同质
使用二项式定理,
发现后面就是 \(1\),
暴力实现即可,时间复杂度 \(O(k^2)\)。
如果你会卷,那可以做到 \(O(k\log k)\),但是不重要。
代码
先理解加强版怎么做。然后直接写加强版即可。
P6031
info
2.6 模拟赛 t3
题解
书接上题,现在得到的式子是:
但是留着第二类斯特林数,复杂度一定无法突破 \(k\log k\) 了。
第二类斯特林数的通项公式:
\[{n\brace m}=\frac 1{m!} \sum^m_{i=0} (-1)^{m-i} \binom m i i^n \]
代入得,
交换求和顺序,
发现 \(\binom i j\) 可以表示成 \(\frac{i!}{j!(i-j)!}\),正好和分母上的 \(i!\) 消掉:
用 \(i-j\) 替换掉 \(i\),
把 \((-p)\) 多余的项分到前面:
发现现在 \(-1\) 的系数变成了 \(2j\),可以消掉了。顺便把 \(n^{\underline{i+j}}\) 拆成两段:\(n^{\underline j}\times (n-j)^{\underline i}\)
发现 \(\frac{(n-j)^{\underline i}}{i!}\) 恰好就是 \(\binom{n-j}{i}\):
\(-p\) 不好处理,下文记 \(p\) 为原来的 \(-p\)。
我们尝试能不能递推 \(f(j)\):
把相似的东西提出来:
Lemma:
\[\binom{n-j+1}{i} - \binom{n-j}{i}= \binom{n-j}{i-1} \]Proof:\(\binom{x-1}{y}+\binom{x-1}{y-1}=\binom x y\)。
所以 \(\binom x y -\binom {x-1}{y}=\binom{x-1}{y-1}\)
代入进去就是:
用 \(i-1\) 代替 \(i\):
用 \(f(j)\) 代替第一项的和式:
把中括号拆开:
提取公因式:
杨辉三角递推式逆运用:
将这个式子的来源 \(f(j-1)-f(j)\) 代入:
整理一下:
组合式不易处理,转化成下降幂:
把 \((n-j)^{\underline{k-j+1}}\) 拆开:
答案就是
预处理下降幂、阶乘、阶乘逆、普通幂即可。
时间复杂度 \(O(n)\)。
代码
Submission。
想题记录(2)
前一篇卡的写起来很难受。
wtcqwq
2.7-
P1527
info
紫
tag:整体二分、二维树状数组
思考路径
看到 \(k\) 小这样的关键词,直接想到整体二分。
可以参考 P3834 的操作,只不过一维变成了二维。
我们重新梳理一下整体二分的操作:
-
执行整体二分函数:参数中有两个区间 \([ql,qr]\) 和 \([l,r]\)。
表示目前的问询列表里第 \([ql,qr]\) 位的问询答案都 \(\in [l,r]\)。
-
我们指定 \(mid=\frac{l+r}2\)。
将 \([l,mid]\) 的操作部署。
如果达到了 \(k\) 个(或其他的某种情况,关键词就是达成了条件),则将这个问询 \(Q\) 放入问询集合 \(Q_1\) 中。
反之,则将这个问询 \(Q\) 先减去 \([l,mid]\) 的贡献,然后放入问询集合 \(Q_2\) 中。
-
将 \(Q_1,Q_2\) 的问询放到一起。然后分裂成两个区间,递归执行整体二分函数。
此时调用的情况就是
Sol(Q1,l,mid)
和Sol(Q2,mid+1,r)
。其中
Q1
和Q2
表示放到一起后表示 \(Q_1\) 和 \(Q_2\) 的两个区间。
发现其他步骤在这里都是套路的,考虑怎么快速部署 \([l,mid]\) 的操作。可以使用二维树状数组,单次查询/修改复杂度 \(O(\log^2n)\)。
加上整体二分的复杂度也就是 \(O(n\log^3n)\)。
代码
Submission。
总结
- 整体二分框架复习。
- 整体二分中涉及一步问询的重编号,即排序后的 \(id\) 数组需要反复调用。很多时候前面给定的 \(qid\in [ql,qr]\),实际上我们到原数据应该用 \(id[qid]\)。
- 二维树状数组的板子。
- cdq 分治和整体二分是同一种分治思想在不同维度发挥作用的体现
- 不要真的去二分值域,不然还得需要离散化,常数更大。把矩阵中的所有元素按照权值排序,二分在答案在排序之后的数组中的位置即可。(因为答案一定是矩阵中存在的值,所以在这些值里面二分就好了。)
P5787
info
蓝。
tag:线段树合并
思考路径
二分图的性质
是一个二分图当且仅当没有奇环。
Lemma 1:一个图 \(G\) 是一个二分图的充分必要条件是,图中不存在一个环 \(C\),使得 \(|C| \equiv 1\pmod 2\)。
充分性:对于任意一个二分图,由于每个部分内部都没有边,因此一个点从出去自己部分再回到自己部分都是经过两条边,充分性得证。
必要性:对于一个没有奇环的图,任意钦定一个点为黑色,然后与它相连的点为白色,与白色相连的点为黑色,将整个图染色,我们发现出现同色点之间存在一条边的条件就是存在奇环,所以必要性得证。
发现奇环性质可以用扩展域并查集维护。不可以路径压缩,所以下文的 \(p_u\) 表示的严格意义上 \(u\) 的父亲。
不难发现,我们可以将 \(u\) 分裂成两个点。
这样的话,任意一条 \(u_1 \to u_2\) 的路径都一定经过奇数条边,(但在原图上)实际上还是走到了 \(u\) 点本身,此时构成了奇环。
此时问题转化成了:
存在 \(m\) 条边,每条边在 \([l_i,r_i]\) 现时存在,连接 \(u_{i_1}\leftrightarrow v_{i_2}\) 和 \(u_{i_2} \leftrightarrow v_{i_1}\)。试判断每一时间刻是否存在 \(i_1\) 和 \(i_2\) 可达的情况。
考虑线段树分治,对时间轴建立线段树。发现 \(T_{u}\) 记录 \([l,r]\) 时间刻内一直存在的边。
发现加边操作此时直接加上了时间刻的维度,不需要可以维护时间。同理地,在查询时,我们可以一次性维护一个区间。
如果把一个区间一直存在的边全都连上也没出现奇环的情况的话,我们就可以往下拆,拆成两个区间继续处理。发现者两个区间的处理都基于父节点已经处理过的扩展域并查集上。
发现一个区间做完以后,要在扩展域并查集上拆回来,这样的话才能回退到父节点。这个怎么解决呢?
在每一次连边的时候加入栈中。进入一个线段树节点前维护一个栈顶编号。回溯时,出栈至上文的栈顶编号,每一次把 \(p_u\) 更新为自己(\(u\))即可。
扩展域并查集需要用随机权值或按秩合并维护,时间复杂度 \(O(\log n)\)。路径压缩是不行的,因为我们需要记录事实的父亲编号。
线段树共有 \(\log k\) 层,可证时间复杂度 \(O(m\log n\log k)\)。
代码
Submission。
总结
- 线段树合并的框架。如果发现一条边/一个物件 etc. 只对一个时段 \([l_i,r_i]\) 有作用的时候,不妨用线段树分治来做
- 需要回溯的时候,要严格地做到”谁污染谁治理“,不能大刀阔斧地 \(O(n^{?})\) 重置,要不然复杂度是假的。
- 异曲同工之妙的还有线段树建图。
- 一个图是二分图的充分必要条件是不存在奇环。
P4766
info
蓝。
tag:区间 dp、笛卡尔树
思考路径
发现我们可以把攻击的时刻作为下标,变成一道数组个数计数。
准确的来说,设 \(f_t\) 是 \(t\) 时刻花费的成本。
则题意转化成了:
对于每一个 \(i\) 都成立,要求 \(\sum f_t\) 最小化。
设 \(dp_{l,r}\) 表示只考虑 \(l\le a_i \le b_i\le r\) 内的约束,符合条件的最小代价。
发现将两个区间合并时,原来就在两个区间里的可以直接用 \(dp\) 数值,需要考虑跨两个区间的贡献。
也就是枚举分界点 \(x\),满足 \(l\le x \le r\),记 \(cost(l,r,x)\) 表示 \(l\le a_i \le x\le b_i \le r\) 的所有 \(d_i\) 之和。
则不难发现
做完了。预处理 \(cost(l,r,x)\) 即可。
代码
预计 10min。现在是 14:49。
现在是 15:02,submission。
总结
- 发现一维 dp 不好做的时候不妨考虑区间 dp,进一步地如果涉及开始时间结束时间,二维 dp 不妨设定为 \(l\le st_i\le ed_i\le r\) 的才算,这样好处理。
- 笛卡尔树是一种思想,这道题本质上是在笛卡尔树上 dp。
CF1442D
info
紫。
tag:线段树分治、背包
思考路径
可爱题。
首先,不降这个条件启发我们考虑挖掘一些性质。
直觉上,如果我们一个数组开始选了,但是只选一半,一定是不优的。尝试来证明这个东西。
Lemma:如果开始选一个,在操作次数足够的情况下,优先选完。
如果我们在两个数组中第一个没选的数分别是 \(A_i=x\) 和 \(B_j=y\)。
如果 \(x>y\),由 \(y\ge \max^{j-1}_{k=1} B_j\) 得 \(x> \max^{j-1}_{k=1} B_j\)。那么我们选上 \(A_i=x\),删去 \(B_{j-1}\) ,一定更优秀。
不断这么替换,一定能将 \(A\) 和 \(B\) 其中某一个删空。
枚举最后一个因为操作数不足导致没选完的数组是哪个 以及 选到了什么位置。
剩下的数组,要选必须全部选完,要不就必须全部不选。所以可以整体成另外一个问题。
Transformed Problem. 背包容量是 \(k'\),每一个物品的代价是 \(t_i\),价值是 \(\sum a_{i,k}\)。不能选某个特定的物品 \(j\),求不超过容量的最大价值,对所有不同的 \(j\) 和某个范围的 \(k'\) 都要求出答案。
发现是线段树分治类似的典题。直接维护即可。
代码
现在是 15:59,期望 15min。
Submission
总结
- 线段树分治本身不是一种算法,而是一种思想。本题不涉及任何线段树的函数,但本质也是线段树分治。
- 证明用到了调整法,这种如果我可以干决策 \(A\),就一定可以干决策 \(A'\),可以干决策 \(A''\),最后发现原来还可以干决策 \(B\),得证了。
CF1768E
info
Eason2009 讲课题。
蓝。*2300
tag:人类智慧、分类讨论、组合数
思考路径
发现连续做同一个操作毫无价值。所以一定是交替来做。
手玩发现任何一个序列至多经过 3 次操作都会有序。
Lemma:任意 \(1\sim 3n\) 的排列经过 \(3\) 次操作都会有序。
Proof:
发现操作 \(1\to\) 操作 \(2\to\) 操作 \(1\) 的情况是:
一次操作在变换的区间的前 \(n\) 个,一定积累了 \(n\) 个比它们大的。一次操作在变换的区间的后 \(n\) 个,一定积累了 \(n\) 个比它们小的。
显然这不重不漏。
三次操作后 \([1,n],[n+1,2n],[2n+1,3n]\) 各自积累了两次”是变换的区间“。对于 \([1,n]\),这是两次 “积累了 \(n\) 个比它们大的”,所以至少有 \(2n\) 个比它们大。另外两个区域同理。
再,显然两次操作后,每 \(n\) 个之间一定变得有序。
然后我们分讨一下:
-
\(f(p)=0\)
只有已经有序一种情况,且无贡献。
-
\(f(p)\le1\)
要么 \([2n+1,3n]\) 恰好覆盖了 \([2n+1,3n]\) 且恰好有序,要么 \([1,n]\) 恰好覆盖了 \([1,n]\) 且恰好有序。
发现这样的个数是 \(2\times\big[(2n)!\big]-n!\)。
-
\(f(p)\le2\)
\(p_{[1,2n]}\) 包括了 \([1,n]\) 或 \(p_{n+1,3n}\) 包括了 \([2n+1,3n]\)。
在 \(2n\) 个位置里选 \(n\) 个,恰好是 \(\binom{2n}{n}\)。
这 \(n\) 个数可以任意排列,也就是 \(n!\)。
剩下的 \(2n\) 个数可以任意排列,也就是 \(2n!\)。
所以两者各有 \(\binom{2n}{n} \times n!\times (2n)!\) 种情况,考虑是否存在交叉。
显然存在。
枚举 \(p_{[1,2n]}\) 区间内 \([n+1,2n]\) 的数有几个,然后可以组合数计算重复:
\[\sum^n_{i=0} \binom{2n-i}{n}\binom{n}{i}^2(n!)^3 \]所以 \(f(p)\le 2\) 的总排列个数就是
\[2\binom{2n}{n}\times n!\times (2n)!-\sum^n_{i=0} \binom{2n-i}{n}\binom{n}{i}^2(n!)^3 \] -
\(f(p)\le 3\)
是全集,也就是 \((3n)!\)。
发现答案是
也就是
把前面的代进来,直接算就行了。
代码
Submission。
总结
- 本题中 \(f(p)\) 是骗得,实际上只有 \(3\),可以朴素地分类讨论。
- \(f(p)=0/1/2/3\) 细节很多,可以转化成 \(f(p)\le 0/1/2/3\),然后做容斥,这样就好做很多了。
- 本题是典型的,先知道结果后知道约束,然后对着约束推式子即可。
ARC110D
info
蓝。1thenzoo9 讲课题。
跟 joeyj 一起想的。
tag:组合数、组合意义
思考路径
考虑组合数的意义,这个东西等价于:
有 \(n\) 组球,每组有 \(a_i\) 个黑球,把不超过 \(m-\sum a_i\) 个球插进去,求总方案数。
枚举插进去几个:
这个东西发现就是:
\(m\) 太大了,再转化一步,方便暴力算就是
直接 \(O(n+\sum a)\) 算即可。
代码
现在是 16:52,五分钟。
现在是 16:58,submission。
总结
- 看起来很奇怪的,带有组合数的式子,不妨把里面的一些元素当作一个整体,能不能成为别样的组合意义。
- \(\binom n a=\binom n{n-a}\) 虽然听起来简单,但是如果 \(n\) 大 \(a\) 小,这可能有用。
ARC106D
info
蓝。1thenzoo9 讲课题。
tag:组合数学
思考路径
推式子。
容斥:
发现剩下的都是好求的,考虑怎么算
可以二项式定理:
移动求和符号的顺序:
设 \(f(x)=\sum^n_{l=1} a_l^x\)
则答案为:
\(f(x)\) 对于每一个 \((x,k)\) 做,发现可以 \(O(kn)\) 地预处理。整个式子求也就是 \(O(k)\) 或 \(O(k^2)\) 的。
题目要求 \(1\le x \le k\),时间复杂度 \(O(k^2+kn)\) 或 \(O(k^3+kn)\)。我写的后者也无压力通过。
代码
Submission。
总结
-
二项式定理:
\[(a+b)^k=\sum^k_{i=0 }\binom k ia^ib^{k-i} \] -
\[\sum_i \sum_j a_ib_j=\Big(\sum_i a_i\Big)\Big(\sum_jb_j\Big) \]
调换 \(\sum\) 符号的顺序,使得两个 \(\sum\) 之间的项只跟对应的 \(\sum\) 的内容有关系方便预处理。
ARC067E
info
紫。1thenzoo9 讲课题。没懂有什么可讲之处。至少我是能一眼
tag:dp
思考路径
发现 \(n\le 10^3\),可以肆无忌惮地设状态。
直接设 \(f_{i,j}\) 表示目前考虑到人数为 \(i\) 的组,一共已经放了 \(j\) 个人的方案数。
然后考虑 \(i\) 放了 \(k\) 组,显然 \(k\in \set{0}\cup[c_i,d_i]\)。
然后转移即可:
其中,\(g_{i,k}\) 表示有 \(ik\) 个人,\(i\) 个人为一组,分成 \(k\) 组的方案数。
\(O(n^2)\) 预处理出 \(g_{i,k}\),然后算 \(f_{i,j}\) 即可。
看起来是 \(O(n^2)\) 个状态和 \(O(n)\) 的转移,但是考虑到 \(ki\le j\),这构成了调和级数。所以实际的时间复杂度是 \(O(n^2\log n)\)。
代码
Submission。
总结
- 调和级数分析复杂度,在对 值的出现次数 和 总和 做限制时很好用。
- 对 值的出现次数 做限制时,可以直接对出现次数做 dp。
- 跟 值得出现次数 有关系的题目,还经常是根号分治做。
CF1781F
info
紫。
tag:dp、组合数、括号匹配
思考路径
典型的括号序列的 trick 包括把括号序列转成 \(+1\) 或 \(-1\)。
设 \(s\) 表示此时括号序列的前缀和。
此时合法扩展序列的充分必要条件就是 \(\min s=0,s_n=0\)。
本题中,加入一个 (
的同时一定加入一个 )
,亦即总和始终为 \(0\),只需要处理 \(\min s=0\) 即可。
那这样的话,加入 ()
就相当于把原来的 \(x\) 扩展成 \([x,x+1,x]\);
加入 )(
就相当于把原来的 \(x\) 扩展成 \([x,x-1,x]\)。
题解
设 \(f_{n,x}\) 表示执行 \(n\) 次操作,\(\min s=-x\) 的方案数。
加入 ()
的话,我们需要把 (
前、()
中和 )
后的东西拆开来考虑。
枚举前两段分别有多少个:
加入 )(
的话,其实是一样的,枚举前两段分别有多少个,只有 \(x+1\) 改成了 \(x-1\)。
加起来即可。发现这样的话时间复杂度至少是 \(O(n^4)\)。
进一步发现 \(i\) 和 \(j\) 组合数一步是可以互换的,也就是
把只跟 \(j\) 有关系的项拿出来:
发现后面这个和式含有很多个 \(n-1-j\),记为 \(t\)。
也就是
是卷积的形式,可以预处理。
时间复杂度就降到 \(O(n^3)\) 了。
因为是算概率,所以最后要除以 \((2n-1)!!\)。
代码
Submission。
CF1572C
info
紫。*2700。
思考路径
设 \(dp_{i,j}\) 表示 \([i,j]\) 最多能省几次。
发现如果一次也不省的话,答案就是 \(n-1\)。只要钦定一个位置不动,剩下都跟这个位置改到一样就可以了。
所以答案就是 \(n-1-dp_{1,n}\)。
怎么转移这个 \(dp_{i,j}\) 呢。如果我们优化一个区间 \([i,j]\),一定是 \(a_i=a_j\) 且把 \((i,j)\) 里每一个数都改成一样的,然后再一起改成 \(a_i\) 就行了,这样能省一次。
看看能不能找到牛性质。如果有两个区间 \([i,j],[i',j']\) 满足 \(i<i'<j<j'\),那肯定不能同时优化。
直接区间 dp 就行了。转移枚举中间点直接做?