51nod 1020 逆序排列
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1020
题意:
思路:
一开始用了三重循环。。。
设f(n,k)表示n个数的排列中逆序数个数为k的排列数。
最大的数n可能会排在第n-i位,从而产生i个与n有关的逆序对,去掉n之后,剩下的n-1个数的排列有k-i个逆序对。所以,f(n,k)=求和(f(n-1,k-i))(0<=i<n)。
同理有f(n,k-1)=求和(f(n-1,k-1-i))(0<=i<n)。
两式相减,可得f(n,k)-f(n,k-1)=f(n-1,k)-f(n-1,k-n)。
递推公式为f(n,k)=f(n,k-1)+f(n-1,k)-f(n-1,k-n)。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=1000+5; 16 const int mod = 1e9+7; 17 18 int n, k; 19 int dp[maxn][20005]; 20 21 void init() 22 { 23 for (int i = 1; i <= 1000; ++i) 24 dp[i][0] = 1; 25 for (int i = 2; i <= 1000; ++i) 26 { 27 for (int j = 1; j <= i * (i - 1) / 2 && j <= 20000; ++j) 28 { 29 dp[i][j] = (dp[i][j - 1] + dp[i - 1][j]) % mod; 30 if (j - i >= 0) 31 dp[i][j] -= dp[i - 1][j - i]; 32 dp[i][j] = (dp[i][j] + mod) % mod; 33 } 34 } 35 } 36 37 int main() 38 { 39 //freopen("in.txt","r",stdin); 40 int T; 41 init(); 42 scanf("%d", &T); 43 while (T--) 44 { 45 scanf("%d%d", &n, &k); 46 printf("%d\n", dp[n][k]); 47 } 48 49 }