给一个n个数的排列,求其向后k个的排列。
这里有一种字典序模拟法。
1:找到最靠后的x,使a[x]<a[x+1]
2:找到最小的a[y],使a[y]>a[x]
3:交换a[x],a[y]
4:把序列(x+1..n)翻转。
每进行一次上述过程,就向下推了一个排列。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 program pku1833(input,output); 2 var 3 a : array[0..2000] of longint; 4 n : longint; 5 k : longint; 6 cases : longint; 7 procedure init; 8 var 9 i : longint; 10 begin 11 fillchar(a,sizeof(a),0); 12 readln(n,k); 13 for i:=1 to n do 14 read(a[i]); 15 readln; 16 end; { init } 17 procedure swap(var aa,bb :longint ); 18 var 19 tt : longint; 20 begin 21 tt:=aa; 22 aa:=bb; 23 bb:=tt; 24 end; { swap } 25 procedure main; 26 var 27 i : longint; 28 x,y : longint; 29 begin 30 while k>0 do 31 begin 32 dec(k); 33 i:=n; 34 while (i>0)and(a[i]>a[i+1]) do 35 dec(i); 36 x:=i; 37 if i=0 then 38 begin 39 for i:=1 to n do 40 a[i]:=i; 41 end 42 else 43 begin 44 a[0]:=maxint; 45 y:=0; 46 for i:=x+1 to n do 47 if (a[i]>a[x])and(a[i] >1 do 51 swap(a[x+i],a[n-i+1]); 52 end; 53 end; 54 end; { main } 55 procedure print; 56 var 57 i : longint; 58 begin 59 for i:=1 to n-1 do 60 write(a[i],' '); 61 writeln(a[n]); 62 end; { print } 63 begin 64 readln(cases); 65 while cases>0 do 66 begin 67 dec(cases); 68 init; 69 main; 70 print; 71 end; 72 end.