bzoj3622
容斥原理
看见恰好k个就要容斥
g[i]表示有几个b比a小
dp[i][j]表示前i个数至少有j个大的方案数,dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(g[i]-j+1),就是可以不匹配,或者在剩下的g[i]-j+1选一个
然后就是容斥了,那个系数搞的不是很清楚,和spring一样
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2005, P = 1e9 + 9; int n, k; ll ans; ll a[N], b[N], inv[N], facinv[N], fac[N], dp[N][N], g[N]; ll C(int n, int m) { return fac[n] * facinv[m] % P * facinv[n - m] % P; } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++i) scanf("%d", &b[i]); if((n + k) & 1) { puts("0"); return 0; } k += (n - k) >> 1; sort(a + 1, a + n + 1); sort(b + 1, b + n + 1); inv[1] = 1; fac[0] = facinv[0] = 1; for(int i = 1; i <= n; ++i) { if(i != 1) inv[i] = (P - P / i) * inv[P % i] % P; facinv[i] = facinv[i - 1] * inv[i] % P; fac[i] = fac[i - 1] * i % P; } for(int i = 1, j = 0; i <= n; ++i) { while(a[i] > b[j + 1] && j + 1 <= n) ++j; g[i] = j; } for(int i = 0; i <= n; ++i) dp[i][0] = 1; for(int i = 1; i <= n; ++i) for(int j = 1; j <= g[i]; ++j) dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] * (g[i] - j + 1) % P) % P; for(int i = k; i <= n; ++i) ans = ((ans + (((i - k) & 1) ? -1 : 1) * dp[n][i] * fac[n - i] % P * C(i, k) % P) % P + P) % P; printf("%lld\n", ans); return 0; }