【SSL 1475】俄罗斯套娃

题目大意:

求长度为 (n) 的排列,逆序对个数小于等于 (k) 的排列个数。

正文:

(f_{i,j}) 表示前 (i) 位有 (j) 个逆序对的方案数,由于第 (i) 位能为前 (i-1) 位贡献,动态转移方程是:

[f_{i,j}=sum_{l=0}^{i-1}f_{i-1,j-l} ]

但这个时间复杂度是 (O(nk^2)),我们要开一个前缀和,顺便滚动一下,确保时空都不会超。

代码:

ll n, k;
ll f[4][N], ans, sum;

int main()
{
	scanf ("%lld%lld", &n, &k);
	f[1][0] = 1LL;
	for (ll i = 2; i <= n; i++)
	{
		sum = 0LL;
		for (ll j = 0; j <= k; j++)
		{
			if(i <= j) sum = (sum - f[(i - 1) & 1][j - i] + mod) % mod;
			sum = (sum + f[(i - 1) & 1][j]) % mod;
			f[i&1][j] = sum;
		}
	}
	for (int i = 0; i <= k; i++)
		ans = (ans + f[n & 1][i]) % mod;
	printf("%lld", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/13497412.html