卡尔文球锦标赛
真实讨厌\(10000\)过\(n^2\)的题目。。。
首先这道题目要明白是怎么按照字典序排序的。由于球队都是按照球队里面最小编号的人排序的,我们就从小到大地考虑每个人在哪一支球队。对第\(i\)个人来说,他可以加入之前的一个球队(此时之前要出现过这支球队),也可以新组建一支球队(此时新组建的这个球队的编号是之前球队最大编号加一)
但是现在还是没有什么思路,于是我们像装饰围栏这道题目一样直接先尝试用试填法:假设我们当前考虑到了第\(i\)位,我们枚举第\(i\)位的数字是什么,假设是\(j\)
当\(j<a_i\)时,注意题目给的序列一定是合法的,也就是说\(a_i\)要么等于\(\overset{i-1}{\underset{k=1}{\max}}a_k+1\),要么属于\([1,\overset{i-1}{\underset{k=1}{\max}}a_k]\),那么我们只用考虑:剩下的\(n-i\)个人,第一个人可以填\([1,\overset{i-1}{\underset{k=1}{\max}}a_k+1]\)的所有合法的序列个数
当\(j=a_i\)时,我们接着往下面考虑就好了
按照以上想法,不难设计出状态:\(f[i][j]\)表示有\(i\)个人,第一个人可以填的数字为\([1,j]\)的总方案数。注意此时表示前面已经填了的数字为\([1,j-1]\),所以有\(f[i][j]=(j-1)\times f[i-1][j]+f[i-1][j+1]\),前面的乘积项表示第一个人填的数字为\([1,j-1]\),后面的一项表示第一个人填的数字为\(j\)
这里肯定要用滚动数组优化。如果只是求出\(f\),那么普通的滚动数组优化就好了,然而我们求数组的方向与用数组的方向却不一致。就是说,假设我们在试填中(这里滚动数组优化,肯定必须边试填边求\(f\))让\(i\)从\(1\)开始逐渐增大到\(n\),那么我们当前求的是\(f[i]\),用的确实\(f[n-i]\),这肯定就没有办法;于是我们必须要让两者方向一致,由于是DP数组在滚动,所以我们方便“用”的一方。具体见代码。注意,代码中f[j]=((ll)(j-1)*f[j]+f[j+1])%p;
求的\(f[j]\)表示的是\(f[n-i+1][j]\)