时间限制: 10000ms 内存限制: 131072kB
描述 问题概括: n 个元素的排序一共有 n! 个,询问排列中逆序对个数为 m 个的排列有多少个。 输入 输入文件仅一行有两个正整数 n , m 输出 仅有一行 , 即满足要求的排列的个数
样例输入 3 2
样例输出 2提示
对于 20% 的数据, n<=10
对于 40% 的数据, n<=20
对于 100% 的数据, 1<=n<=50 m<=(n-1)*n/2
思路:动态规划
f[i,j] 表示1-i形成的排列恰好有j个逆序对的个数
那么
f[i,j]:=sum(f[i-1,j-k]) (0<=k<=i-1,k<=j)
n<=50所以还要用高精度。
来源:tyvj 柯桥中学60周年欢乐赛
提交地址:http://hzoi.openjudge.cn/codewaysky/1016/
ac程序:
type arr=array[0..100] of longint;
var f:array[0..50,0..1250] of arr;
{f:array[0..50,0..50] of longint;}
n,m,i,j,k:longint;
procedure jia(var a,b:arr);
var i,j,len:longint;
begin
len:=a[0];
if len<b[0] then len:=b[0];
for i:=1 to len do
begin
a[i]:=a[i]+b[i];
a[i+1]:=a[i+1]+a[i] div 10000;
a[i]:=a[i] mod 10000;
end;
if a[len+1]>0 then inc(len);
a[0]:=len;
end;
procedure print;
var i,len:longint;
begin
len:=f[n,m][0];
write(f[n,m][len]);
for i:=len-1 downto 1 do
begin
if f[n,m][i]<1000 then write(0);
if f[n,m][i]<100 then write(0);
if f[n,m][i]<10 then write(0);
write(f[n,m][i]);
end;
end;
begin
readln(n,m);
f[0,0][0]:=1;
for i:=1 to n do
for j:=1 to m do
begin
f[i,0][0]:=1; f[i,0][1]:=1;
f[i,j][0]:=1;
for k:=0 to i-1 do
if j>=k then
jia(f[i,j],f[i-1,j-k]);
end;
print;
{f[1,0]:=1;
for i:=1 to n do
begin
f[i,0]:=1;
for j:=1 to m do
for k:=0 to i-1 do
if j>=k then
f[i,j]:=f[i,j]+f[i-1,j-k];
end;}
{writeln(f[n,m]);}
end.