【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;
}
posted @ 2020-08-13 16:59  Jayun  阅读(145)  评论(0编辑  收藏  举报