题目: | 火星人 | |
来源: | Noip2004P4 | |
题目大意: | 给定一个数N,给定一个数M,给定一个由1~N组成的排列数,求第M个比它大的 1~N的排列数 | |
数据范围: | 1<=N<=10000、1<=M<=100 | |
样例: | 5 3 1 2 3 4 5 | 1 2 4 5 3 |
做题思路: | N很大,导致无法康拓了。。M很小,枚举?嗯 从右到左扫描,只要数字在不断递增(从右到左递增)就继续向左,知道找到一个不 递增的元素,记录他的下标(设为p),然后在递增区间内找到一个大于它并且最接 近他的元素,交换2个的位子,然后再将p后的元素按递减排列(从右到左递减), 由于交换后还是有序的,所以只需要首尾互换即可。 | |
知识点: | 枚举 |
var
m,n,i:longint;
a:array[1..10000] of longint;
//=============================================
procedure change;
var i,p,min,x,tmp:longint;
begin
p:=n-1;
min:=n;
while(a[p]>a[p+1]) do dec(p);
fori:=p+1 to n do
if(a[i]-a[p]<min) and (a[i]-a[p]>0) then
begin
min:=a[i]-a[p];
x:=i;
end;
tmp:=a[x]; a[x]:=a[p]; a[p]:=tmp;
fori:=p+1 to (n-p)div 2+p do
begin
tmp:=a[i]; a[i]:=a[n+1-i+p]; a[n+1-i+p]:=tmp;
end;
//==============================================
end;
begin
readln(n);
readln(m);
fori:=1 to n do
read(a[i]);
fori:=1 to m do
change;
fori:=1 to n-1 do
write(a[i],' ');
writeln(a[n]);
end.
题目来源:
http://yuanti.tyvj.cn:8080/Problem_Show.asp?id=1045