题目描述

我们说(i,j)是a1,a2,…,aN的一个逆序对当且仅当i<j且ai>a j。例如2,4,1,3,5的逆序对有3个,分别为(1,3),(2,3),(2,4)。现在已知N和K,求1…N的所有特定排列,这些排列的逆序对的数量恰好为K。输出这些特定排列的数量。

例如N=5,K=3的时候,满足条件的排列有15个,它们是:

1,2,5,4,3 1,3,4,5,2 1,3,5,2,4 1,4,2,5,3 1,4,3,2,5 1,5,2,3,4 2,1,4,5,3 2,1,5,3,4 2,3,1,5,4 2,3,4,1,5

2,4,1,3,5 3,1,2,5,4 3,1,4,2,5 3,2,1,4,5 4,1,2,3,5

输入输出格式

输入格式:

输入第一行有两个整数N和K。(N≤100,K≤N*(N-1)/2)

输出格式:

将1…N的逆序对数量为K的特定排列的数量输出。为了避免高精度计算,请将结果mod 10000以后再输出!

输入输出样例

输入样例#1:

5 3
输出样例#1:

15
先搜索。。。
ngs(k的最大值) n:f(k為0,1,2,3...)

0  0:1
 0  1:1
 1  2: 1,1
 3  3:1,2, 2
 6  4:1,3, 5,  6
10  5:1,4, 9, 15, 20, 22
15  6:1,5,14, 29, 49, 71,  90,  101, 101
21  7:1,6,20, 49, 98,169, 259,  359, 455,  531,  573,  573
28  8:1,7,27, 76,174,343, 602,  961,1415, 1940, 2493, 3017, 3450, 3736, 3836
36  9:1,8,35,111,285, 628,1230,2191,3606, 5545, 8031,11021,14395,17957,21450, 24584, 27073, 28675, 29228

45 10:1,9,44,155,440,1068,2298,4489,8095,13640,21670,32683,47043,64889,86054,110010,135853,162337,187959,211089,230131,243694,250749,250749
(註:應該是對稱的,為了不超行,我刪掉了後面的。)
看了一下上面的,相信聰明的,你,一定發現了規律。(呵呵,不可能的!)
if(j<=ngs[i]/2){
f[i][j]=f[i-1][j]+f[i][j-1];
if(j>=i) f[i][j]-=f[i-1][j-i];
}
else f[i][j]=f[i][ngs[i]-j];
呵呵,是不是很神奇。
因為數值很大,需要mod,這裡有一些小技巧。
代碼實現:
 #include<cstdio>
#include<iostream>
using namespace std;
const int mod=;
int n,k,ngs[],f[][];
int main(){
scanf("%d%d",&n,&k);f[][]=f[][]=;//初始化。
for(int i=;i<=n;i++){
ngs[i]=ngs[i-]+i-;//你懂的。
for(int j=;j<=ngs[i];j++){
f[i-][j]%=mod;//mod的小技巧。
if(j<=ngs[i]/){//DP方程應用。
f[i][j]=f[i-][j]+f[i][j-];
if(j>=i) f[i][j]-=f[i-][j-i];
}
else f[i][j]=f[i][ngs[i]-j];
}
}
printf("%d\n",f[n][k]%mod);//mod的小技巧。
return ;
}

這絕不是一道搜索題~

05-11 22:51