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

posted @ 2021-07-05 13:35  pigstd  阅读(126)  评论(0编辑  收藏  举报