bzoj4361:isn(dp+容斥+树状数组)

题面

darkbzoj

题解

\(g[i]\)表示长度为\(i\)的非降序列的个数

那么,

\[ans = \sum_{i=1}^{n}g[i]*(n-i)!-g[i+1]*(n-i-1)!*(i+1) \]

怎么求\(g[i]\)

\(f[i][j]\)为长度为\(i\)的非降序列,以最后一个数是\(j\)的数量

\(f[i][j] = \sum f[i-1][k](k<=j)\)

这样是\(O(n^3)\)

因为带修改,所以树状数组优化转移

复杂度:\(O(n^2logn)\)

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register

using namespace std;
template<class T> inline void read(T &x) {
	x = 0; RG char c = getchar(); bool f = 0;
	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
	x = f ? -x : x;
	return ;
}
template<class T> inline void write(T x) {
	if (!x) {putchar(48);return ;}
	if (x < 0) x = -x, putchar('-');
	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N = 2010, Mod = 1e9 + 7;
int n, a[N], b[N], f[N][N], m;
void pls(int &x, int y) {
	x += y;
	if (x >= Mod) x -= Mod;
	if (x < 0) x += Mod;
}
#define lowbit(x) (x & (-x))
void add(int id, int x, int k) { for (; x <= m; x += lowbit(x)) pls(f[id][x], k); }
int sum(int id, int x) { int res = 0; for (; x; x -= lowbit(x)) pls(res, f[id][x]); return res; }
int g[N], fac[N];

int main() {
	read(n);
	for (int i = 1; i <= n; i++) read(a[i]), b[i] = a[i];
	sort(b + 1, b + 1 + n);
	m = unique(b + 1, b + 1 + n) - b - 1;
	for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + 1 + m, a[i]) - b;
	add(0, 1, 1);
	for (int i = 1; i <= n; i++)
		for (int j = i; j >= 1; j--) {
			int tmp = sum(j - 1, a[i]);
			pls(g[j], tmp);
			add(j, a[i], tmp);
		}
	int ans = 0;
	fac[0] = 1;
	for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
	for (int i = 1; i <= n; i++) pls(ans, (1ll * fac[n - i] * g[i] % Mod - 1ll * fac[n - i - 1] * g[i + 1] % Mod * (i + 1) % Mod + Mod) % Mod);
	printf("%d\n", ans);
	return 0;
}

posted @ 2019-03-28 07:55  zzy2005  阅读(193)  评论(0编辑  收藏  举报