bzoj3622 已经没有什么好害怕的了
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3622
【题解】
XJOI noip模拟题的一题吧
这题统计方法用容斥
f[i,j]表示前i个人,j个一定赢,其他不管的方案数。
先考虑一定赢的转移,最后乘不论输赢的排列即可。
那么ans[n] = f[n,n]
ans[i] = f[n,i] - sigma(ans[j] * C(j,i)),其中j>i
j个人赢了,挑任意i个人出来都符合条件,减去
最后答案为ans[nWin]。
# include <vector> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e3 + 10; const int mod = 1e9+9; # define RG register # define ST static int n, K, a[M], b[M]; int f[M][M], C[M][M], fac[M], ok[M], ans[M]; int main() { cin >> n >> K; if((n+K)&1) { puts("0"); return 0; } fac[0] = 1; for (int i=1; i<=n; ++i) fac[i] = 1ll * fac[i-1] * i % mod; C[0][0] = 1; for (int i=1; i<=n; ++i) { C[i][0] = 1; for (int j=1; j<=i; ++j) { C[i][j] = C[i-1][j] + C[i-1][j-1]; if(C[i][j] >= mod) C[i][j] -= mod; } } for (int i=1; i<=n; ++i) scanf("%d", a+i); for (int i=1; i<=n; ++i) scanf("%d", b+i); int nWin = (n+K)/2, nLose = (n-K)/2; sort(a+1, a+n+1); sort(b+1, b+n+1); for (int i=1; i<=n; ++i) ok[i] = upper_bound(b+1, b+n+1, a[i]) - b - 1; f[0][0] = 1; for (int i=1; i<=n; ++i) { for (int j=0; j<=i; ++j) { f[i][j] = f[i-1][j]; if(j && ok[i]-(j-1) > 0) { f[i][j] += 1ll * f[i-1][j-1] * (ok[i] - (j-1)) % mod; if(f[i][j] >= mod) f[i][j] -= mod; } } } int *F = f[n]; for (int i=0; i<=n; ++i) F[i] = 1ll * F[i] * fac[n-i] % mod; for (int i=n; i>=0; --i) { ans[i] = F[i]; for (int j=i+1; j<=n; ++j) { ans[i] -= 1ll * ans[j] * C[j][i] % mod; if(ans[i] < 0) ans[i] += mod; } } cout << ans[nWin] << endl; return 0; }