题目大意:题目讲得很复杂,其实数学模型很简单。就是 1~n 这 n 个数,若给出一个排列 a1,a2,a3…an ,对所有 i 满足 (ai-a(i+1))(ai-a(i-1))>0 (其实也就是数按大小的波浪形排列),则该排列符合要求。各个排列之间按字典序排序。(当 n=3 时,满足条件的序列依次为( 1 , 3 , 2 ),( 2 , 1 , 3 ),( 2 , 3 , 1 ),( 3 , 1 , 2 ))
输入 N,C, 要求输出 n=N 时的第 C 个符合要求的序列。
分析:有 100 个测试数据,直接搜索不行。我们通过计算区间,从前往后依次确定各个位置的数字。
先做预处理, T[i][j]表示 当 n=i , a1=j ( 1<=j<=n )时,存在的符合前面要求的序列的个数 。这样就可以根据数组 T[N][] 和 C 的值,得到 a1 的值。当a1的值确定了, C-= ∑ T[n][j](1<=j<=a1-1),n=N-1 , 问题的规模变为了 N-1 , 得到了一个子问题。可是,当 a1!=1&&a1!=n, 后面的数就不连续了,这时候还能把它当成子问题来处理吗?答案是肯定的,我们只要在心里想,把后面 N-1 个数中,所有大于 a1 的数都减 1 。这样,数又会连续了。我们就可以继续根据 T [N-1][]来确定 n=N-1 时的第一个数 的值,也即a2,以此类推,直到确定所有数。需要注意的是,因为数必须成波浪形,在实际的代码中,我们用 M,W 两个数组来取代 T , M[n][k] 表示 a1=k,a2>a1 时的情况, W[n][k] 表示 a1=k,a2<a1 时的情况。因为是按字典序排列,对相同的 k ,我们总是优先考虑 W 。
W , M 的计算可以采用如下递推方法:
M[n] [x] = ∑ W[n-1] [i] (1<=i<=x-1)
W[n] [x] = ∑ M[n-1] [i] (x<=i<=n-1)( 我们只要在心里想 , 把后面 N-1 个数中 , 所有大于等于 x 的数都加 1)
M[n] [x] = W[n] [n-x+1] ( 长度从小到大排列的木条 , 第 x 根与第 n-x+1 根是对应的 )
需要指出的是,在放第一个数的时候, W 和 M 方式都要考虑,而后面的数,则根据前面的情况选择是 W 还是 M 。还有,在最后输出的时候,也会稍微有点纠结。