题目链接:https://www.luogu.org/problemnew/show/P1521
显然是一道DP题。。。
我们可以定义dp[i][j]表示放完第i个数,产生j个逆序对的方案数,因为这样有利于状态转移,每次只需要考虑第i个数放在哪,就知道新产生了几对逆序对。
容易得到dp[i][j] = sum{dp[i-1][j-l]},0<=l<=i-1。
还可以这样理解,我们考虑第i个数放了什么,因为是个排列,所以从0对到i-1对逆序对会因放完第i个数产生且只产生一次,状态转移方程和上面就一样了。
我感觉,关于求方案数的DP题,初始条件的处理也比较难想,经常是一些极端情况,比如这里,对于任意i,j=0时dp值为1。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 3 const int maxn = 205, maxk = 205, p = 1e9 + 7; 4 5 int dp[maxn][maxk]; 6 7 int main() { 8 int n, k; 9 scanf("%d%d", &n, &k); 10 for (int i = 1; i <= n; ++i) dp[i][0] = 1; 11 for (int i = 2; i <= n; ++i) 12 for (int j = 1; j <= k; ++j) 13 for (int l = 0; l <= i - 1 && j - l >= 0; ++l) 14 dp[i][j] = (dp[i][j] + dp[i - 1][j - l]) % p; 15 printf("%d", dp[n][k]); 16 return 0; 17 }