☆逆序对 动态规划+高精度

 
     
 
From KQZXCMH
逆序对
 
     

 

 

 

 

背景 Background

 

 

柯桥中学60周年校庆欢乐赛第3题

 

 

 

 

 

 

 

描述 Description

 

 

  问题概括:n个元素的排序一共有n!个,询问排列中逆序对个数为m个的排列有多少个。

 

 

 

 

 

 

 

输入格式 Input Format

 

 

输入文件仅一行有两个正整数n,m

 

 

 

 

 

 

 

输出格式 Output Format

 

 

仅有一行,即满足要求的排列的个数

 

 

 

 

 

 

 

样例输入 Sample Input [复制数据]

 

 

3 2

 

 

 

 

 

 

 

样例输出 Sample Output [复制数据]

 

 

2

 

 

 

 

 

 

 

时间限制 Time Limitation

 

 

1s

 

 

 

 

 

 

 

注释 Hint

 

 

对于20%的数据,n<=10
对于40%的数据,n<=20
对于100%的数据,1<=n<=50  m<=(n-1)*n/2

 

Problem 3 逆序对 pair
考察算法 动态规划+高精度
题目大意 求1~N 的排列中有多少个排列的逆序对个数刚好为 M个。
主要算法 本题的动态规划算法很容易想到。F[i,j]表示 1~i 形成的排列中恰好有 j对
逆序对的个数。那么动态规划就可以用插入法来做,将 i+1 插入到i+1 个位置
中可以增加0~i个逆序对。
i-1
转移方程为 f[i, j]= f[i-1, j -k](j >=k)

k=0
因为 n<=50,结果就要用高精度来做了。

 

const md=1000000;
type arr=array[0..100] of longint;
var f:array[0..50,0..500] of arr;
n,m,i,j,k,sum:longint;
procedure jia(var a,b:arr);
var i,j,len:longint;
begin
 if a[0]>b[0] then len:=a[0]
 else 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 md;
   a[i]:=a[i] mod md;
  end;
 if a[len+1]>0 then inc(len);
 a[0]:=len;
end;
procedure print(a:arr);
var i:longint;
begin
 write(a[a[0]]);
 for i:=a[0]-1 downto 1 do
  begin
   if a[i]<100000 then write(0);
   if a[i]<10000 then write(0);
   if a[i]<1000 then write(0);
   if a[i]<100 then write(0);
   if a[i]<10 then write(0);
   write(a[i]);
  end;
end;
begin
 {assign(input,'pair.in'); assign(output,'pair.out');
 reset(input); rewrite(output);}
 readln(n,m);
 f[0,0][0]:=1; f[0,0][1]:=1;
 for i:=1 to n do
  for j:=0 to m do
   for k:=0 to i-1 do
    if k<=j then
    jia(f[i,j],f[i-1,j-k]);
 print(f[n,m]);
 {close(input); close(output);} 
end.


 

 

你可能感兴趣的:(模拟题,高精度,动态规划,S!,tyvj,恶心的题目)