CF1542 题解
文化课选手只能打打 div2。
CF1542A
注意到奇数必须由一奇加一偶组成,判断奇数和偶数的数量是否一样即可。
code。
CF1542B
这个题不比 C 难?
需要观察到一个结论:先乘后加必然是最优的。
为什么呢?如果先加后乘,那么乘法操作相当于是重复了若干次加的操作后在把 \(1\) 乘上 \(a\),那么显然先乘后加显然也可以做到。
然后枚举乘了几次就好了,需要特判 \(a=1\),\(b=1\)。
code。
CF1542C
令 \(g(x)=\operatorname{lcm(1,2\dots x)}\),那么 \(f(x)\) 的意义就是 \(g(f(x)-1)|x\) 且 \(g(f(x)) \not |x\) 。换句话说,\(f(x)=k+1\),\(k\) 表示最大的能使 \(g(k)|x\) 的数。
枚举 \(i\) 考虑 \(f(x) > i\) 的 \(x\) 个数,显然是 \([\frac{n}{g(i)}]\),那么答案就是把这些都加起来再加上 \(n\)。
code。
CF1542D
套路题。对于每个操作 + x
,考虑计算这个操作的贡献,即考虑有多少种情况下 \(x\) 这个数一直被保存到最后。
使用 dp 去计算这个贡献,\(dp_{i,j}\) 表示算到第 \(i\) 个操作的时候,有 \(j\) 个数会优先在它之前被删除的方案数,转移方程很好推,但有些细节。
注意到有可能出现 \(x\) 相同的情况,默认之后的先删除或者之前的先删除即可。
code。
CF1542E E1 E2
蒟蒻不会做数数。
令 \(f_x\) 表示排列长度为 \(x\) 的时候的答案,那么所求的就是 \(f_n\)。
尝试递推出 \(f\)。对于一个新的 \(n\),可以对第一位进行分类讨论:
- 第一位相同,那么这位对于后面的序列的逆序对的贡献也是相同的,所以 \(p_{1\dots n}\) 的逆序对数大于 \(q_{1 \dots n}\) 的逆序对数等价于 \(p_{2\dots n}\) 的逆序对数大于 \(q_{2 \dots n}\) 的逆序对数,字典序大小同理,这又相当于转化成了 \(n-1\) 的时候的情况。第一位有 \(n\) 个选择,那么有 \(f_n = n \times f_{n-1}\)。
- 第一位不同,那么可以尝试枚举 \(p_1\) 和 \(q_1\),显然有 \(p_1<q_1\),这意味着无论后面的排列是什么,字典序的条件已经满足了,而排列 \(p\) 的逆序对数又可以分为 \(p_{2 \dots n}\) 的逆序对和 \(p_1\) 的贡献,后者显然是 \(p_1-1\),所以可以枚举 \(p_{2 \dots n}\) 的逆序对数 \(x\) 和 \(q_{2 \dots n}\) 的逆序对数 \(y\)(\(x+p_1-1>y+p_2-1\)),然后算出 \(n-1\) 的排列中有多少个逆序对数为 \(x,y\) 的,然后乘起来就好。
后者可以先使用一个 dp 解决:\(dp_{i,j}\) 表示长度为 \(i\),逆序对数为 \(j\) 的排列数,转移的时候枚举第一个数然后计算贡献即可。具体的,\(\displaystyle dp_{i,j}=\sum_{k=1}^ndp_{i-1,j-k+1}\),直接算是 \(\mathcal{O}(n^4)\) 的。
然而直接这么做的话时间复杂度是 \(\mathcal{O}(n^7)\) 的根本过不去,注意到枚举了 \(x\) 后 \(y\) 只能为 \(1 \dots (x+p1-p2-1)\),可以计算一下 \(dp_{i,j}\) 的前缀和 \(sum_{i,j}\) 表示长度为 \(i\),逆序对数 \(\le j\) 的排列数,然后就可以优化至 \(\mathcal{O}(n^5)\),足以通过 E1。code。
比赛的时候想到了这里结果没写完 。\fn
考虑优化。发现这份代码可以分成两部分:求出 \(dp_{i,j}\) 的部分和求出 \(f\) 的部分。前者直接使用前缀和优化,一遍算 dp 一遍算前缀和就可优化至 \(\mathcal{O}(n^3)\)。
对于后者,有一个比较好想到的优化就是发现一对 \((p_1,q_1)\) 对 \(f_n\) 产生的贡献只与 \(q_1-p_1\) 有关,枚举 \(q_1-p_1\) 然后乘上一个系数就可以把这部分优化为 \(\mathcal{O}(n^4)\)。这部分的代码。
观察一下剩下的这个东西,我们需要把这个东西优化至 \(\mathcal{O}(n^3)\)。
for (int j=1;j<=i-1;j++)
for (int p1=j+1;p1<=C2(i-1);p1++)
f[i]=(f[i]+dp1[i-1][p1]*sum[i-1][p1-j-1]%Mod*(i-j))%Mod;
考虑交换枚举顺序,先枚举 \(p1\)(即上文中的 \(x\))再枚举 \(j\)(即上文中的 \(q_1-p_1\))。那么对于每个 \(p1\),对于 \(f_n\) 的贡献就是:
\(\displaystyle dp_{i-1,p1}\times \sum_{j=1}^{i-1}sum_{i-1,p1-j-1}\times(i-j)=dp_{i-1,p1}\times (i\times \sum_{j=1}^{i-1}sum_{i-1,p1-j-1}-\sum_{j=1}^{i-1}j\times sum_{i-1,p1-j-1})\)
\(\displaystyle\sum_{j=1}^{i-1}sum_{i-1,p1-j-1}\) 这个东西可以通过对 \(sum_i\) 再做一个前缀和 \(\displaystyle sum2_{i,j}=\sum_{k=0}^jsum_{i,k}\) 从而快速算出,接下来要做的是快速求出 \(\displaystyle \sum_{j=1}^{i-1}j\times sum_{i-1,p1-j-1}\)。
考虑对这个东西进行“递推”。令 \(b_{p1}=\displaystyle \sum_{j=1}^{i-1}j\times sum_{i-1,p1-j-1}\),那么经过一些推导后可以发现 \(\displaystyle b_{p1+1}=b_{p1}+\sum_{j=1}^{i-1}sum_{i-1,p1-j}-(i-1)\times sum_{i-1,p1-i}\),又和 \(sum2\) 有关系,都可以快速求出。综合一下就可以完成整个算法,其中空间不够需要滚动数组,时间复杂度 \(\mathcal{O}(n^3)\),空间复杂度 \(\mathcal{O}(n^2)\)。
code。